I want to use Rust and Juniper to create a GraphQL server. This server has to access the database.
I've been trying to follow this example code from Juniper but it uses an empty Context
to give over to the Schema
; I need to send a pool for database connections.
I want to be able to connect to the GraphQL via POST
, GET
and websockets.
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))
}
However, I get an error:
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
I don't understand enough about the way these values are move
d to solve this issue. How do I solve issues like this?
Thanks to some comments, I figured out a way that the Rust compiler accepts:
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))
}
I don't fully understand why this is necessary, but it works for now.