托管状态的静态生命周期要求

Static lifetime requirements for managed state

我在使用 Rocket 托管 State 时遇到问题。此状态包含数据库连接和该数据库上的游标集合。每一篇论文都有一个关于数据库的参考。

对该状态的操作之一需要在数据库上创建一个新游标并保留它以备后用。不幸的是,我遇到了一生的问题。通常,我处理这些问题没有问题,但现在,我没主意了...

我在一个简短的例子中重现了下面的问题。

#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;

use rocket::State;

struct Database;

impl Database {
    fn create_cursor(&self) -> Cursor {
        Cursor { database: self }
    }
}

struct Cursor<'a> {
    database: &'a Database
}

struct Controller<'a> {
    database: Database,
    cursors: Vec<Cursor<'a>>,
}

impl<'a> Controller<'a> {
    fn do_work(&'a mut self) {
        let cursor = self.database.create_cursor();
        self.cursors.push(cursor)
    }
}

fn main() {
    let database = Database;
    let controller = Controller { database, cursors: Vec::new() };

    rocket::ignite()
        .manage(controller)
        .launch();
}

#[get("/")]
pub fn do_work_route(
    mut controller: State<'static, Controller<'static>>
) -> &'static str {
    controller.do_work();
    "Something..."
}
error[E0621]: explicit lifetime required in the type of `__req`
  --> src/main.rs:42:9
   |
40 | #[get("/")]
   | ----------- help: add explicit lifetime `'static` to the type of `__req`: `&'_b rocket::Request<'static>`
41 | pub fn do_work_route(
42 |     mut controller: State<'static, Controller<'static>>
   |         ^^^^^^^^^^ lifetime `'static` required

如有任何线索,我们将不胜感激。与此同时,我会继续挖掘。

非常感谢!

你写的 Controller 结构是自引用的,这是不可能的:https://users.rust-lang.org/t/how-to-write-software-without-self-referential-structs/13819

原因是当 Controller 被移动时,其 cursors 成员中对数据库的引用将变得无效,因为其 database 成员的内存位置发生了变化。

最好的前进方式可能是退后一步,思考一个非自我参照的设计。一种可能的解决方案是使数据库成为 static variable,然后您的游标可以存储 &'static Database 个引用。

如果失败,上面的 link 提到了 rental 箱子,但它似乎不太好用。