Задать вопрос
@TicSo

Как внести данные из приложения AXUM в вектор?

От клиента из браузера методом POST (const response = await fetch)
отправляю запрос с данными на сервер AXUM.
Хочу сохранять такие данные в вектор.

Из раздела Shared mutable state

_docs.rs/axum/latest/axum/extract/struct.State.html
сохранять в тип данных String, как в рекомендации, - получается.

Если в структуре меняю тип со строки на вектор, то код не работает.
делал так:
код

use axum::extract::State;
use std::sync::{Arc, Mutex};

#[derive(Debug, Clone)]
struct AppState {
// d: Arc<Mutex<String>>,
   d: Arc<Mutex<Vec<String>>>,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {

   let state = AppState {
      d: Arc::new(Mutex::new("abcde".to_owned())), 
      // ^_работает, когда в структуре не вектор, а строка d: Arc<Mutex<String>>,

      // варианты кода для вектора - не работают:
      // d: Arc::new(Mutex::new(Vec::new())),            // error[E0614]: type `()` cannot be dereferenced
      // d: Arc::new(Mutex::new(vec!["abc".to_owned()])),
   };

// ...
   let app = Router::new()
                  .route("/info", post(create_user))
                  .with_state(state);

   let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
   axum::serve(listener, app).await.unwrap();

// ...
Ok(())
}



async fn create_user(
   State(state): State<AppState>, 
   Json(payload): Json<FromBrowser>,    
) -> (StatusCode, Json<User>) {
   // ...
  let user = User {username: payload.username};

   { 
      let mut d = state.d.lock().expect("mutex was poisoned");
      *d = user.username.to_owned();  
      // ^_ так для строки работает, варианты кода ниже для вектора - нет:
      // *d.push(user.username.to_owned());
      // *d.push(Arc::new(Mutex::new(vec![user.username.to_owned()])));
   }
   println!("state = {:?}", state);
   (StatusCode::CREATED, Json(user))
}


Подскажите, пожалуйста, как исправить код и есть ли разные решения с точки зрения скорости работы для случаев:
- такой вектор только читают
- вектор читают и изменяют.
Будет ли быстрее обработка данных, если в структуре вектор будет хранить не String, а &str?
  • Вопрос задан
  • 42 просмотра
Подписаться 1 Сложный 3 комментария
Решения вопроса 1
vabka
@vabka Куратор тега Rust
Кажется, ты просто в своих же типах запутался. Всё работает (ниже работающий код)

Подскажите, пожалуйста, как исправить код и есть ли разные решения с точки зрения скорости работы для случаев:
- такой вектор только читают
- вектор читают и изменяют.

Если только читают, то 1 раз его проинициализировал, а в стейте пусть лежит Arc без mutex.
Если и читают и пишут, то RwLock, но стоит подумать над структурами данных, тк у тебя ради добавления одной записи блокируется весь список. Что-нибудь на основе связных списков например позволит не блочить весь вектор.

use axum::extract::State;
use axum::http::StatusCode;
use axum::routing::{get, post};
use axum::{Json, Router};
use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex};

#[derive(Debug, Clone)]
struct AppState {
    d: Arc<Mutex<Vec<String>>>,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let state = AppState {
        d: Arc::new(Mutex::new(vec![])),
    };

    let app = Router::new()
        .route("/info", post(create_user))
        .route("/list_users", get(list_users))
        .with_state(state);

    let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
        .await
        .unwrap();
    axum::serve(listener, app).await.unwrap();

    Ok(())
}

#[derive(Deserialize)]
pub struct FromBrowser {
    username: String,
}

#[derive(Serialize)]
pub struct User {
    username: String,
}

async fn create_user(
    State(state): State<AppState>,
    Json(payload): Json<FromBrowser>,
) -> (StatusCode, Json<User>) {
    // ...
    let user = User {
        username: payload.username,
    };

    {
        let mut d = state.d.lock().expect("mutex was poisoned");
        d.push(user.username.to_owned());
    }
    println!("state = {:?}", state);
    (StatusCode::CREATED, Json(user))
}

async fn list_users(State(state): State<AppState>) -> (StatusCode, Json<Vec<String>>) {
    let users = state.d.lock().expect("mutex was poisoned").clone();
    (StatusCode::OK, Json(users))
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы