【问题标题】:How do I use PickleDB with Rocket/Juniper Context?如何将 PickleDB 与 Rocket/Juniper 上下文一起使用?
【发布时间】:2020-05-25 01:14:44
【问题描述】:

我正在尝试使用 PickleDB 编写一个基于 Rocket / Juniper / Rust 的 GraphQL 服务器 - 一个内存键/值存储。

pickle db 在开始时创建/加载并交给rocket进行管理:

fn rocket() -> Rocket {
    let pickle_path = var_os(String::from("PICKLE_PATH")).unwrap_or(OsString::from("pickle.db"));
    let pickle_db_dump_policy = PickleDbDumpPolicy::PeriodicDump(Duration::from_secs(120));
    let pickle_serialization_method = SerializationMethod::Bin;

    let pickle_db: PickleDb = match Path::new(&pickle_path).exists() {
        false => PickleDb::new(pickle_path, pickle_db_dump_policy, pickle_serialization_method),
        true => PickleDb::load(pickle_path, pickle_db_dump_policy, pickle_serialization_method).unwrap(),
    };

    rocket::ignite()
        .manage(Schema::new(Query, Mutation))
        .manage(pickle_db)
        .mount(
            "/",
            routes![graphiql, get_graphql_handler, post_graphql_handler],
        )
}

我想从我的 Guard 中的 Rocket State 中检索 PickleDb 实例:

pub struct Context {
    pickle_db: PickleDb,
}

impl juniper::Context for Context {}

impl<'a, 'r> FromRequest<'a, 'r> for Context {
    type Error = ();

    fn from_request(_request: &'a Request<'r>) -> request::Outcome<Context, ()> {
        let pickle_db = _request.guard::<State<PickleDb>>()?.inner();
        Outcome::Success(Context { pickle_db })
    }
}

这不起作用,因为国家只给了我一个参考:

26 |         Outcome::Success(Context { pickle_db })
   |                                    ^^^^^^^^^ expected struct `pickledb::pickledb::PickleDb`, found `&pickledb::pickledb::PickleDb`

当我更改我的 Context 结构以包含一个引用时,我遇到了我还不熟悉的终身问题:

15 |     pickle_db: &PickleDb,
   |                ^ expected named lifetime parameter

我尝试使用 'static 确实让 rust 很不高兴,我尝试使用 FromRequest 的请求生命周期 (?) 'r,但这也不起作用...

如何让它工作?由于我对生锈很陌生,这是做事的正确方法吗?

【问题讨论】:

    标签: rust rust-rocket


    【解决方案1】:

    我终于有了一个解决方案,尽管对 unsafe 的需求表明它不是最理想的 :)

    #![allow(unsafe_code)]
    use pickledb::{PickleDb, PickleDbDumpPolicy, SerializationMethod};
    use serde::de::DeserializeOwned;
    use serde::Serialize;
    use std::env;
    use std::path::Path;
    use std::time::Duration;
    
    pub static mut PICKLE_DB: Option<PickleDb> = None;
    
    pub fn cache_init() {
        let pickle_path = env::var(String::from("PICKLE_PATH")).unwrap_or(String::from("pickle.db"));
        let pickle_db_dump_policy = PickleDbDumpPolicy::PeriodicDump(Duration::from_secs(120));
        let pickle_serialization_method = SerializationMethod::Json;
        let pickle_db = match Path::new(&pickle_path).exists() {
            false => PickleDb::new(
                pickle_path,
                pickle_db_dump_policy,
                pickle_serialization_method,
            ),
            true => PickleDb::load(
                pickle_path,
                pickle_db_dump_policy,
                pickle_serialization_method,
            )
            .unwrap(),
        };
        unsafe {
            PICKLE_DB = Some(pickle_db);
        }
    }
    
    pub fn cache_get<V>(key: &str) -> Option<V>
    where
        V: DeserializeOwned + std::fmt::Debug,
    {
        unsafe {
            let pickle_db = PICKLE_DB
                .as_ref()
                .expect("cache uninitialized - call cache_init()");
            pickle_db.get::<V>(key)
        }
    }
    
    pub fn cache_set<V>(key: &str, value: &V) -> Result<(), pickledb::error::Error>
    where
        V: Serialize,
    {
        unsafe {
            let pickle_db = PICKLE_DB
                .as_mut()
                .expect("cache uninitialized - call cache_init()");
            pickle_db.set::<V>(key, value)?;
            Ok(())
        }
    }
    

    这可以按预期简单地导入和使用,但我想当负载变高时我会遇到问题......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-20
      • 2019-07-17
      • 2018-10-13
      • 2022-11-03
      • 2016-10-21
      • 2019-05-30
      相关资源
      最近更新 更多