【问题标题】:Injecting a Diesel connection into an Iron middleware将 Diesel 连接注入 Iron 中间件
【发布时间】:2016-10-25 21:48:35
【问题描述】:

在编写我的测试时,我希望能够将连接注入到请求中,以便我可以将整个测试用例包装在一个事务中(即使测试用例中有多个请求)。

我尝试使用 BeforeMiddleware 来执行此操作,我可以在我的测试用例中链接它以插入连接,例如:

pub type DatabaseConnection = PooledConnection<ConnectionManager<PgConnection>>;

pub struct DatabaseOverride {
    conn: DatabaseConnection,
}

impl BeforeMiddleware for DatabaseOverride {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions_mut().entry::<DatabaseOverride>().or_insert(self.conn);
        Ok(())
    }
}

但是,我在尝试执行此操作时遇到编译错误:

error: the trait bound `std::rc::Rc<diesel::pg::connection::raw::RawConnection>: std::marker::Sync` is not satisfied [E0277]
impl BeforeMiddleware for DatabaseOverride {
     ^~~~~~~~~~~~~~~~
help: run `rustc --explain E0277` to see a detailed explanation
note: `std::rc::Rc<diesel::pg::connection::raw::RawConnection>` cannot be shared between threads safely
note: required because it appears within the type `diesel::pg::PgConnection`
note: required because it appears within the type `r2d2::Conn<diesel::pg::PgConnection>`
note: required because it appears within the type `std::option::Option<r2d2::Conn<diesel::pg::PgConnection>>`
note: required because it appears within the type `r2d2::PooledConnection<r2d2_diesel::ConnectionManager<diesel::pg::PgConnection>>`
note: required because it appears within the type `utility::db::DatabaseOverride`
note: required by `iron::BeforeMiddleware`

error: the trait bound `std::cell::Cell<i32>: std::marker::Sync` is not satisfied [E0277]
impl BeforeMiddleware for DatabaseOverride {
     ^~~~~~~~~~~~~~~~
help: run `rustc --explain E0277` to see a detailed explanation
note: `std::cell::Cell<i32>` cannot be shared between threads safely
note: required because it appears within the type `diesel::pg::PgConnection`
note: required because it appears within the type `r2d2::Conn<diesel::pg::PgConnection>`
note: required because it appears within the type `std::option::Option<r2d2::Conn<diesel::pg::PgConnection>>`
note: required because it appears within the type `r2d2::PooledConnection<r2d2_diesel::ConnectionManager<diesel::pg::PgConnection>>`
note: required because it appears within the type `utility::db::DatabaseOverride`
note: required by `iron::BeforeMiddleware`

有没有办法通过柴油机的连接来解决这个问题?我在 Github 上找到了几个使用 pg crate 的示例,但我想继续使用柴油。

【问题讨论】:

  • 我可能是错的(我不在我的 Rust 环境 atm 附近)但你不必实现 typemap 特征或类似的东西才能将其存储在请求扩展中吗?
  • 是的,我已经实现了一个(为简洁起见,我没有在这里发布)。这里的问题是我不能用diesel::pg::PgConnection 初始化BeforeMiddleware,因为PgConnection 没有实现Sync。我希望有人知道解决此限制的方法。
  • 我自己没有使用过diesel,我不确定。然而,它使用任何Cell 类型,甚至是像Rc 这样的不同步智能指针,都会导致它自动无法实现Sync

标签: rust iron rust-diesel


【解决方案1】:

This answer 肯定会解决问题,但不是最优的。如前所述,您不能共享单个连接,因为它不是线程安全的。然而,虽然将其包装在 Mutex 中使其成为线程安全的,但它会强制所有服务器线程使用 single 连接。相反,您想使用连接池。

您可以使用 r2d2r2d2-diesel 板条箱来完成此操作。这将根据需要建立多个连接,并在可能的情况下以线程安全的方式重用它们。

【讨论】:

    【解决方案2】:

    由于没有足够的代码让我重现您的问题,我做了这个:

    use std::cell::Cell;
    
    trait Middleware: Sync {}
    
    struct Unsharable(Cell<bool>);
    
    impl Middleware for Unsharable {}
    
    fn main() {}
    

    同样的错误:

    error: the trait bound `std::cell::Cell<bool>: std::marker::Sync` is not satisfied [E0277]
    impl Middleware for Unsharable {}
         ^~~~~~~~~~
    help: run `rustc --explain E0277` to see a detailed explanation
    note: `std::cell::Cell<bool>` cannot be shared between threads safely
    note: required because it appears within the type `Unsharable`
    note: required by `Middleware`
    

    你可以通过改变类型使其跨线程兼容来解决问题:

    use std::sync::Mutex;
    
    struct Sharable(Mutex<Unsharable>);
    
    impl Middleware for Sharable {}
    

    请注意,Rust 为您做了一件非常好的事情:它阻止您使用在多个线程中调用的不安全类型。


    在编写我的测试时,我希望能够将连接注入到请求中,以便我可以将整个测试用例包装在一个事务中(即使测试用例中有多个请求)。

    我建议架构更改可能会更好。将“Web 框架”的域与“数据库”分开。 Growing Object-Oriented Software, Guided by Tests(强烈推荐的书)的作者提倡这种风格。

    拆开你的代码,这样有一个方法可以简单地接受可以开始/结束事务的某种类型,在那里编写有趣的东西,并彻底测试它。然后在 web 层有足够的胶水代码来创建一个事务对象,然后调用下一层。

    【讨论】:

      猜你喜欢
      • 2020-08-05
      • 2019-05-16
      • 2022-12-10
      • 1970-01-01
      • 1970-01-01
      • 2019-08-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多