Как можно добавить счётчик ответов на запросы от клиента в код сервера, использующего библиотеку axum?

Как можно внедрить переменную `cnt_ajax` в функцию `async fn create_user` в коде AXUM, чтобы использовать её для нумерации ответов, учитывая, что запросы от клиента могут приходить в разной последовательности? Я добавил строку `let cnt_ajax: u32 = 0;` в `main`, но не знаю, как правильно передать эту переменную в функцию `create_user`, используя сигнатуру `async fn create_user(Json(payload): Json, <b>&amp;cnt_ajax: u32,</b> ) -> (StatusCode, Json) {}`.
  • 27 ноября 2024 г. 20:53
Ответы на вопрос 2
Для добавления счётчика запросов в ваш сервер на основе `axum`, вы можете использовать `Arc<Mutex<u32>>` для достижения безопасного многопоточного доступа к переменной-счётчику `cnt_ajax`. Ниже приведён пример, как это можно сделать.

1. Импортируйте необходимые модули:
```rust
use axum::{
    body::Json,
    http::StatusCode,
    Router,
    routing::post,
};
use std::sync::{Arc, Mutex};
use tokio::sync::RwLock;
```

2. Определите функцию `create_user` с использованием счётчика:

```rust
async fn create_user(Json(payload): Json<User>, cnt_ajax: Arc<Mutex<u32>>) -> (StatusCode, Json<UserResponse>) {
    // Увеличивайте счётчик
    let mut cnt = cnt_ajax.lock().unwrap();
    *cnt += 1;

    // Логика создания пользователя
    // ...

    // Например, формируем ответ с номером запроса
    let response = UserResponse { id: /* id нового пользователя */, request_number: *cnt };

    (StatusCode::CREATED, Json(response))
}
```

3. Добавьте счётчик в `main` и передайте его в маршруты:

```rust
#[tokio::main]
async fn main() {
    // Создаем общий счетчик запросов, заключенный в Arc и Mutex
    let cnt_ajax = Arc::new(Mutex::new(0));

    // Формируем маршруты и передаём cnt_ajax.
    let app = Router::new()
        .route("/create_user", post(create_user))
        .layer(axum::AddExtensionLayer::new(cnt_ajax.clone())); // Передаём состояние с помощью расширения

    // Запуск сервера
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}
```

4. В функции `create_user`, для получения доступа к `cnt_ajax`, вызовите его через `.extension()`:

```rust
use axum::extract::Extension;

async fn create_user(Json(payload): Json<User>, Extension(cnt_ajax): Extension<Arc<Mutex<u32>>>) -> (StatusCode, Json<UserResponse>) {
    // Увеличиваем счетчик
    let mut cnt = cnt_ajax.lock().unwrap();
    *cnt += 1;

    // Логика создания пользователя
    // ...

    // Формируем ответ
    let response = UserResponse { id: /* id нового пользователя */, request_number: *cnt };

    (StatusCode::CREATED, Json(response))
}
```

Таким образом, вы можете внедрить переменную `cnt_ajax` в функцию `create_user` и использовать её для нумерации ответов от клиента. Каждый раз, когда клиент отправляет запрос, счётчик будет увеличиваться, и вы сможете использовать его для номеризации ответов.
https://doc.rust-lang.org/std/sync/atomic/struct.A... 

use std::sync::atomic::{AtomicU32, Ordering};

async fn create_user(
    Json(payload): Json<FromBrowser>,
 ) -> (StatusCode, Json<User>) {
    static COUNTER: AtomicU32 = AtomicU32::new(0);

    // подготавливаю данные на отправку в браузер:
    let user = User {
       id: payload.id,
       username: payload.username,
       tm: payload.tm,
       cnt: COUNTER.fetch_add(1, Ordering::SeqCst),   // считаю отправки; 
    };

    (StatusCode::CREATED, Json(user))
 }
Похожие вопросы