将移动的变量重新用于 warp 过滤器

Reusing a moved variable for warp filters

我想使用 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 解决此问题的方式了解不够。我该如何解决此类问题?

感谢一些评论,我找到了 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))
}

我不完全明白为什么这是必要的,但现在可以。