Как внедрить неизменяемый объект в сервисный код в actix-web?

Я использую инфраструктуру actix для создания сервера, который должен поддерживать возможность показывать возраст и баланс пользователю с учетом user_id:

fn show_balance(req: &HttpRequest) -> HttpResponse {
    let client = create_client();
    let user_id = req.match_info().get("user_id").unwrap();
    let balance = client.load_grade(user_id); // Returns a balance as a String
    HttpResponse::Ok()
        .content_type("text/plain")
        .body(format!("Hello! Your balance is {}", balance))
}

fn show_age(req: &HttpRequest) -> HttpResponse {
    let client = create_client();
    let user_id = req.match_info().get("user_id").unwrap();
    let age = client.load_grade(user_id); // Returns an age as a String
    HttpResponse::Ok()
        .content_type("text/plain")
        .body(format!("Hello! Your balance is {}", age))
}

fn main() {
    env::set_var("RUST_LOG", "actix_web=debug");
    env::set_var("RUST_BACKTRACE", "1");
    env_logger::init();
    let sys = actix::System::new("basic-example");

    let addr = server::new(
        || App::new()
            // enable logger
            .middleware(middleware::Logger::default())
            .resource("/balance/{user_id}", |r| r.method(Method::GET).f(show_balance))
            .resource("/age/{user_id}", |r| r.method(Method::GET).f(show_age))
        .bind("127.0.0.1:8080").expect("Can not bind to 127.0.0.1:8080")
        .start();

    println!("Starting http server: 127.0.0.1:8080");
    let _ = sys.run();
}

fn create_client() -> UserDataClient {
    let enviroment = grpcio::EnvBuilder::new().build();
    let channel = grpcio::ChannelBuilder::new(enviroment)
        .connect(API_URL);
    UserDataClient::new(channel)
}

Этот код работает, но меня беспокоит то, что мне нужно создавать клиент (и открывать канал) для каждого входящего запроса, который является неэффективным и читаемым, я думаю, что это хорошая идея, чтобы сделать что-то одноэлементное вместо этого (так как я могу использовать его повторно). Я просмотрел папку с примерами и обнаружил, что пример todo похож на то, что я делаю. Таким образом, я нашел следующие два варианта, чтобы ввести мой client объект (после того, как я создаю один экземпляр этого в main():

  1. Поместите это в состояние приложения
  2. Вставить его как промежуточное ПО ( 1, 2)?

Что лучше / правильнее реализовать?

Я думал о том, чтобы просто передать клиентский объект каждому обработчику в качестве аргумента, но мне не удалось заставить его работать (и все равно не очень хорошо выглядит).

0 ответов

Другие вопросы по тегам