【问题标题】:Reusing a moved variable for warp filters [duplicate]重用变形过滤器的移动变量[重复]
【发布时间】:2021-02-08 23:00:21
【问题描述】:

我想使用 Rust 和 Juniper 创建一个 GraphQL 服务器。此服务器必须访问数据库。

我一直在尝试关注 Juniper 的 this example code,但它使用空的 Context 来让步给 Schema;我需要发送一个用于数据库连接的池。

我希望能够通过POSTGET 和 websockets 连接到 GraphQL。

type RepositoryPool = r2d2::Pool<diesel::r2d2::ConnectionManager<diesel::PgConnection>>;

fn graphql(
    db_pool: RepositoryPool,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
    let state = warp::any().map(move || Context::new(db_pool.clone()));
    let root_node = Arc::new(schema());
    let graphql_filter = make_graphql_filter(schema(), state.boxed());

    let post_filter = warp::post()
        .and(warp::body::content_length_limit(1024 * 16))
        .and(graphql_filter.clone());

    let get_filter = warp::get().and(graphql_filter);

    let ws_filter = warp::ws().map(move |ws: warp::ws::Ws| {
        let root_node = root_node.clone();
        let db_pool = db_pool.clone();
        ws.on_upgrade(move |websocket| async move {
            serve_graphql_ws(
                websocket,
                root_node,
                ConnectionConfig::new(Context::new(db_pool)),
            )
            .map(|r| {
                if let Err(e) = r {
                    println!("Websocket error: {}", e);
                }
            })
            .await
        })
    });

    warp::path("graphql").and(get_filter.or(post_filter).or(ws_filter))
}

但是,我收到一个错误:

error[E0382]: use of moved value: `db_pool`
  --> src\filters.rs:39:34
   |
27 |   db_pool: RepositoryPool,
   |   ------- move occurs because `db_pool` has type `r2d2::Pool<diesel::r2d2::ConnectionManager<diesel::PgConnection>>`, which does not implement the `Copy` trait
28 | ) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
29 |   let state = warp::any().map(move || Context::new(db_pool.clone()));
   |                               -------              ------- variable moved due to use in closure
   |                               |
   |                               value moved into closure here
...
39 |   let ws_filter = warp::ws().map(move |ws: warp::ws::Ws| {
   |                                  ^^^^^^^^^^^^^^^^^^^^^^^ value used here after move
40 |     let root_node = root_node.clone();
41 |     let db_pool = db_pool.clone();
   |                   ------- use occurs due to use in closure

我对这些值的moved 的方式了解不够,无法解决这个问题。如何解决此类问题?

【问题讨论】:

标签: websocket rust graphql juniper rust-warp


【解决方案1】:

感谢一些 cmets,我想出了一个 Rust 编译器接受的方式:

fn graphql(
    db_pool: RepositoryPool,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
    let db_pool_clone = db_pool.clone();
    let state = warp::any().map(move || Context::new(db_pool_clone.clone()));
    let root_node = Arc::new(schema());
    let graphql_filter = make_graphql_filter(schema(), state.boxed());

    let post_filter = warp::post()
        .and(warp::body::content_length_limit(1024 * 16))
        .and(graphql_filter.clone());

    let get_filter = warp::get().and(graphql_filter);

    let ws_filter = warp::ws().map(move |ws: warp::ws::Ws| {
        let root_node = root_node.clone();
        let db_pool = db_pool.clone();
        ws.on_upgrade(move |websocket| async move {
            serve_graphql_ws(
                websocket,
                root_node,
                ConnectionConfig::new(Context::new(db_pool)),
            )
            .map(|r| {
                if let Err(e) = r {
                    println!("Websocket error: {}", e);
                }
            })
            .await
        })
    });

    warp::path("graphql").and(get_filter.or(post_filter).or(ws_filter))
}

我不完全理解为什么这是必要的,但它现在有效。

【讨论】:

  • 这是必要的,因为 move 闭包会将所有引用的 names 移动到闭包内,因此当闭包使用 `db_pool.clone(), Rust immediately moves db_pool` 时创作结束;当闭包运行时,只有克隆说db_pool
  • 顺便说一句,这种情况的常见模式是“精确捕获子句”模式:smallcultfollowing.com/babysteps/blog/2018/04/24/…
猜你喜欢
  • 2020-11-17
  • 1970-01-01
  • 2020-09-04
  • 2021-08-11
  • 2018-10-04
  • 2018-08-20
  • 1970-01-01
  • 1970-01-01
  • 2015-08-24
相关资源
最近更新 更多