0

I'm using seanmonstar/warp to build my rest service and faced the problem related to lifetimes. Here is how my application starting code looks like:

struct MyModelStruct {
    //...
}

struct Database {
    //...
}

impl Database {
    fn connect(/* ommited */) -> Database {
        //...
    }
}

fn start_app(db: &Database) -> () {
    let route = warp::post()
        .and(warp::path!("action" / u32))
        .and(warp::body::json::<MyModelSctruct>())
        .map(|_, _| {
             //use db
        })
    warp::serve(route).run(/* address */);
}

I got the error:

error[E0621]: explicit lifetime required in the type of `db`
  --> src/application.rs:69:5
   |
46 | fn start_app(db: &Database) -> (){
   |                         -------- help: add explicit lifetime `'static` to the type of `db`: `&'static db::Database`
...
69 |     warp::serve(route);
   |     ^^^^^^^^^^^ lifetime `'static` required

This is because the warp::serve function is defined as

/// Create a `Server` with the provided `Filter`.
pub fn serve<F>(filter: F) -> Server<F>
where
    F: Filter + Clone + Send + Sync + 'static,
    F::Extract: Reply,
    F::Error: IsReject,
{
    Server {
        pipeline: false,
        filter,
    }
}

So the 'static lifetime is required explicitly. The problem is it is used as

let db = Database::connect(...);
start_app(&db);

So the lifetime of db is not static. Is there a way to workaround this?

Some Name
  • 8,555
  • 5
  • 27
  • 77
  • Do you need to pass a reference to `start_app`, or could you pass ownership? If you can't pass a reference, could you pass an `Rc` or `Arc`? – loganfsmyth Jul 26 '20 at 23:20
  • @loganfsmyth You mean wrap the `Database` in `Arc` and pass the ownership to `Arc`? – Some Name Jul 26 '20 at 23:24
  • @loganfsmyth Reference is highly desirable since the `Database` is owned by something else. – Some Name Jul 26 '20 at 23:25
  • 1
    `serve` requires a `'static`, so it needs to be able to guarantee that the database won't be dropped while the server is running. If something else has exclusive ownership of the Database, there is no way to guarantee that. – loganfsmyth Jul 26 '20 at 23:32
  • @loganfsmyth So insted I should pass `Arc` and enforce the closure to take ownership on it... ? – Some Name Jul 26 '20 at 23:44

1 Answers1

3

A 'static lifetime means that the function is guaranteed to not reference any data that could be dropped before the function itself is dropped. Because you are currently passing in a &Database, your function cannot be 'static (unless you were somehow passing a &'static Database, which would require explicitly creating a memory leak).

The only way around this would be for you to either pass Database or Arc<Database> or something along that would allow access so that the function has a strong reference to the Database and can guarantee that the DB will continue to exist as long as the function does.

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251