I am having trouble passing additional state to my service function, but I can't sort out the lifetimes in the closures. None of the tutorials seem to address it:
https://docs.rs/hyper/0.13.4/hyper/server/index.html
https://docs.rs/hyper/0.13.4/hyper/service/fn.make_service_fn.html
Relevant code:
#[tokio::main]
async fn main() {
let addr = ([127, 0, 0, 1], 8080).into();
let db = Arc::new(Mutex::new(Slab::new()));
let server = Server::bind(&addr).serve(make_service_fn(|_conn| async {
let db = db.clone();
Ok::<_, Infallible>(service_fn(move |req| serve_req(req, &db)))
}));
if let Err(e) = server.await {
eprintln!("server error: {}", e)
}
}
Errors:
Compiling hyper-microservice v0.1.0 (/data/repos/rust/hyper-microservice)
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:121:66
|
121 | Ok::<_, Infallible>(service_fn(move |req| serve_req(req, &db)))
| ^^^
|
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 121:40...
--> src/main.rs:121:40
|
121 | Ok::<_, Infallible>(service_fn(move |req| serve_req(req, &db)))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `db`
--> src/main.rs:121:66
|
121 | Ok::<_, Infallible>(service_fn(move |req| serve_req(req, &db)))
| ^^^
note: but, the lifetime must be valid for the expression at 121:29...
--> src/main.rs:121:29
|
121 | Ok::<_, Infallible>(service_fn(move |req| serve_req(req, &db)))
| ^^^^^^^^^^
My understanding is that make_service_fn
is responsible for returning a ServiceFn
that can be used to serve requests for a given connection, and it creates a new ServiceFn
for every connection. Now, service_fn
takes a function/closure that that takes a request and returns a Future that returns a response (or error). And, as I understand it, the ServiceFn
may be executed multiple times per connection. So roughly, each client gets it's own thread, which executes an async service function for each request on that connection (so the same client could make multiple requests on the same connection and be served concurrently within the same thread).
I believe that what might be happening is that the compiler thinks that one of the closures might outlive db?
|_conn| async
=>move |_conn| async
? – Legitimize