use crate::engine::database::no_database::NoDatabaseEndpoint;
use crate::engine::database::DatabaseEndpoint;
use crate::engine::events::EventHandlerBag;
use crate::engine::loader::{NodeLoader, RelLoader};
use crate::engine::resolvers::{ResolverFunc, Resolvers};
use crate::engine::schema::Info;
use crate::engine::validators::Validators;
use crate::Error;
use juniper::Context;
use std::collections::HashMap;
use std::fmt::Debug;
use std::fmt::Formatter;
use ultra_batch::Batcher;
#[allow(clippy::upper_case_acronyms)]
pub struct GraphQLContext<RequestCtx: RequestContext> {
pool: <<RequestCtx as RequestContext>::DBEndpointType as DatabaseEndpoint>::PoolType,
node_batcher: Batcher<NodeLoader<RequestCtx>>,
rel_batcher: Batcher<RelLoader<RequestCtx>>,
resolvers: Resolvers<RequestCtx>,
validators: Validators,
event_handlers: EventHandlerBag<RequestCtx>,
request_ctx: Option<RequestCtx>,
version: Option<String>,
metadata: HashMap<String, String>,
}
impl<RequestCtx> GraphQLContext<RequestCtx>
where
RequestCtx: RequestContext,
{
#[allow(clippy::too_many_arguments)]
pub(crate) fn new(
pool: <<RequestCtx as RequestContext>::DBEndpointType as DatabaseEndpoint>::PoolType,
resolvers: Resolvers<RequestCtx>,
validators: Validators,
event_handlers: EventHandlerBag<RequestCtx>,
request_ctx: Option<RequestCtx>,
version: Option<String>,
metadata: HashMap<String, String>,
info: Info,
) -> GraphQLContext<RequestCtx> {
let node_batcher =
Batcher::build(NodeLoader::<RequestCtx>::new(pool.clone(), info)).finish();
let rel_batcher = Batcher::build(RelLoader::<RequestCtx>::new(pool.clone())).finish();
GraphQLContext {
pool,
node_batcher,
rel_batcher,
resolvers,
validators,
event_handlers,
request_ctx,
version,
metadata,
}
}
pub fn pool(
&self,
) -> &<<RequestCtx as RequestContext>::DBEndpointType as DatabaseEndpoint>::PoolType {
&self.pool
}
pub fn resolver(&self, name: &str) -> Result<&ResolverFunc<RequestCtx>, Error> {
self.resolvers
.get(name)
.map(|b| b.as_ref())
.ok_or_else(|| Error::ResolverNotFound {
name: name.to_owned(),
})
}
pub fn validators(&self) -> &Validators {
&self.validators
}
pub fn event_handlers(&self) -> &EventHandlerBag<RequestCtx> {
&self.event_handlers
}
pub fn version(&self) -> Option<&String> {
self.version.as_ref()
}
pub fn request_context(&self) -> Option<&RequestCtx> {
self.request_ctx.as_ref()
}
pub fn metadata(&self) -> &HashMap<String, String> {
&self.metadata
}
pub fn node_batcher(&self) -> &Batcher<NodeLoader<RequestCtx>> {
&self.node_batcher
}
pub fn rel_batcher(&self) -> &Batcher<RelLoader<RequestCtx>> {
&self.rel_batcher
}
}
impl<RequestCtx> Context for GraphQLContext<RequestCtx> where RequestCtx: RequestContext {}
impl<RequestCtx> Debug for GraphQLContext<RequestCtx>
where
RequestCtx: RequestContext,
{
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
f.debug_struct("GraphQLContext")
.field("request_ctx", &self.request_ctx)
.field("version", &self.version)
.finish()
}
}
pub trait RequestContext: 'static + Clone + Debug + Send + Sync {
type DBEndpointType: DatabaseEndpoint;
fn new() -> Self;
}
impl RequestContext for () {
type DBEndpointType = NoDatabaseEndpoint;
fn new() {}
}
#[cfg(test)]
mod tests {
use super::GraphQLContext;
use crate::engine::database::no_database::NoDatabaseEndpoint;
use crate::engine::database::DatabaseEndpoint;
use crate::engine::events::EventHandlerBag;
use crate::engine::resolvers::Resolvers;
use crate::engine::schema::Info;
use crate::engine::validators::Validators;
use std::collections::HashMap;
use std::sync::Arc;
#[tokio::test]
async fn engine_new() {
let ne = NoDatabaseEndpoint {};
let resolvers: Resolvers<()> = Resolvers::new();
let validators: Validators = Validators::new();
let _gqlctx: GraphQLContext<()> = GraphQLContext::new(
ne.pool()
.await
.expect("Expected to unwrap Cypher database pool."),
resolvers,
validators,
EventHandlerBag::new(),
Some(()),
None,
HashMap::<String, String>::new(),
Info::new(String::new(), Arc::new(HashMap::new())),
);
}
}