1

I have defined the application state to have a lifetime parameter, as below:

pub struct ServiceState<'a> {
    pub db: sync::Mutex<Database<'a>>,
}

impl<'a> ServiceState<'a> {
    pub async fn new() -> Result<ServiceState<'a>, Error> {
        let db = database::ConnectionPool::new(CONFIGURATION).await?;
        Ok(ServiceState {
            db: sync::Mutex::new(db),
        })
    }
}

and passed it to the actix server as expected, code below:

#[actix_rt::main]
async fn main() -> std::io::Result<()> {
    let state = model::ServiceState::new();
    let uri = connection::uri();
    let data = web::Data::new(state);
    let mut server = HttpServer::new(move || {
        App::new()
            .app_data(data.clone())
            .configure(routes::configuration)
    });

    // ... more code ...

    server.run().await
}

When I try to access the database stored in application state in my route, see below:

pub async fn do_stuff(
    state: web::Data<model::ServiceState<'_>>,
    json: web::Json<model::RequestBody>,
) -> HttpResponse {
    let _data = model::RequestBody::from(json);

    // MutexGuard<'_, Database<'_>> is just to show what types are being used

    let db: MutexGuard<'_, Database<'_>> = state.db.lock().unwrap();
    let _client = db.client().await.unwrap();

    // ... would be other logic here but commented out to isolate error

    HttpResponse::Ok().finish()
}

I get the following errors:

error[E0597]: `state` does not live long enough
  --> src/handler/verification.rs:12:48
   |
8  |     state: web::Data<model::ServiceState<'_>>,
   |     ----- lifetime `'1` appears in the type of `state`
...
12 |     let mut db: MutexGuard<'_, Database<'_>> = state.db.lock().unwrap();
   |                                                ^^^^^----------
   |                                                |
   |                                                borrowed value does not live long enough
   |                                                argument requires that `state` is borrowed for `'1`
...
32 | }
   | - `state` dropped here while still borrowed

error[E0597]: `db` does not live long enough
  --> src/handler/verification.rs:13:19
   |
8  |     state: web::Data<model::ServiceState<'_>>,
   |     ----- lifetime `'1` appears in the type of `state`
...
13 |     let _client = db.client().await.unwrap();
   |                   ^^---------
   |                   |
   |                   borrowed value does not live long enough
   |                   argument requires that `db` is borrowed for `'1`
...
32 | }
   | - `db` dropped here while still borrowed

I have been poking and prodding this for a while, experimenting with different lifetimes, specifying that one should live longer than another, etc to no avail. I think I am missing a concrete understanding of why this error message is happening. My thought process is both client and db are borrowed by inside the function so I am confused as to why it should be a problem that they are dropped when the function ends.

I will note that my code (larger than this example) all worked fine until I introduced a lifetime parameter to the app state, so I assume that I am just not providing some lifetime parameters that the compiler previously eluded.

I hope the current example is enough to at least gain some insight as to what is going wrong.

Any help would be greatly appreciated, I am fairly new to rust/actix and struggling to get this (what seems like should be fairly common and simple use case) to work.

Marcus Ruddick
  • 9,795
  • 7
  • 28
  • 43
  • I cannot answer your question, but I can suggest you also joining the Rust Slack channels (https://rust-slack.herokuapp.com/invite). There's quite some folks there who could lend you a hand. – Orco Sep 26 '20 at 18:58
  • @Marcus Ruddick did you ever find the issue here? I just encountered a similar thing when trying to write middleware. – Brecht De Rooms Feb 20 '23 at 19:00
  • Didn't you forget to await your ServiceState? `let state = model::ServiceState::new().await;`? – rubdos Feb 21 '23 at 10:10

0 Answers0