问题描述
我想使用Rust和Juniper创建GraphQL服务器。该服务器必须访问数据库。
我一直在尝试遵循Juniper的this example code,但它使用一个空的Context
来取代Schema
;我需要发送一个数据库连接池。
我希望能够通过POST
,GET
和网络套接字连接到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
我对move
d这些值来解决此问题的方式了解得还不够。我该如何解决这样的问题?
解决方法
感谢一些评论,我找出了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))
}
我不完全理解为什么这样做是必要的,但目前仍然有效。