1

I'm using actix framework to build a server that should support an opportunity to show both age/balance to a user given a 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)
}

This code works, but my concern is that I have to create a client (and open a channel) for every incoming request which is inefficient and readable, I think it's a good idea to make sort of a singleton instead (since I can reuse it). I looked through the example folder and found that todo example is kinda similar to what I'm doing. So I found the following two options to inject my client object (after I create a single instance of it in main():

  1. Put it in an app state
  2. Inject it as a middleware (1, 2)?

What's the best/correct one to implement?

I thought about just passing a client object to every handler as an argument but I didn't manage to make it work (and doesn't look good anyway).

H. Desane
  • 593
  • 1
  • 8
  • 16
  • *which is inefficient and readable* — why do you think it's inefficient? Why is being readable a bad thing? *a good idea to make sort of a singleton* — singletons are often (but not always) a **bad** pattern. – Shepmaster Jan 30 '19 at 16:51
  • *What's the best/correct one to implement* — This sounds like an opinion-based question. "Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise." – Shepmaster Jan 30 '19 at 16:52

0 Answers0