dataloader 0.9.1

Rust implementation of Facebook's DataLoader using futures.
Documentation
use async_graphql::{Context, EmptyMutation, EmptySubscription, Schema};
use async_trait::async_trait;
use dataloader::cached::Loader;
use dataloader::BatchFn;
use fake::faker::company::en::CompanyName;
use fake::faker::name::en::Name;
use fake::{Dummy, Fake, Faker};
use futures::executor::block_on;
use std::collections::HashMap;

pub struct CultBatcher;

#[async_trait]
impl BatchFn<i32, Cult> for CultBatcher {
    type Error = ();

    async fn load(&self, keys: &[i32]) -> HashMap<i32, Result<Cult, Self::Error>> {
        println!("load cult by batch {:?}", keys);
        let ret = keys
            .iter()
            .map(|k| {
                let mut cult: Cult = Faker.fake();
                cult.id = k.clone();
                (k.clone(), Ok(cult))
            })
            .collect();
        ret
    }
}

#[derive(Clone)]
pub struct AppContext {
    cult_loader: Loader<i32, Cult, (), CultBatcher>,
}

impl AppContext {
    pub fn new() -> AppContext {
        AppContext {
            cult_loader: Loader::new(CultBatcher),
        }
    }
}

struct Query;

#[async_graphql::Object]
impl Query {
    #[field]
    async fn persons(&self, _ctx: &Context<'_>) -> Vec<Person> {
        let persons = fake::vec![Person; 10..20];
        persons
    }

    #[field]
    async fn cult(&self, ctx: &Context<'_>, id: i32) -> Cult {
        ctx.data::<AppContext>()
            .cult_loader
            .load(id)
            .await
            .expect("get cult")
    }
}

#[derive(Debug, Clone, Dummy)]
pub struct Person {
    #[dummy(faker = "1..999")]
    pub id: i32,
    #[dummy(faker = "Name()")]
    pub name: String,
    #[dummy(faker = "1..999")]
    pub cult: i32,
}

#[async_graphql::Object]
impl Person {
    #[field]
    async fn id(&self) -> i32 {
        self.id
    }

    #[field]
    async fn name(&self) -> &str {
        self.name.as_str()
    }

    #[field]
    async fn cult(&self, ctx: &Context<'_>) -> Cult {
        let fut = ctx.data::<AppContext>().cult_loader.load(self.cult);
        fut.await.expect("get cult")
    }

    #[field]
    async fn cult_by_id(&self, ctx: &Context<'_>, id: i32) -> Cult {
        ctx.data::<AppContext>()
            .cult_loader
            .load(id)
            .await
            .expect("get cult")
    }
}

#[derive(Debug, Clone, Dummy)]
pub struct Cult {
    #[dummy(faker = "1..999")]
    pub id: i32,
    #[dummy(faker = "CompanyName()")]
    pub name: String,
}

#[async_graphql::Object]
impl Cult {
    #[field]
    async fn id(&self) -> i32 {
        self.id
    }

    #[field]
    async fn name(&self) -> &str {
        self.name.as_str()
    }
}

fn main() {
    let schema = Schema::new(Query, EmptyMutation, EmptySubscription).data(AppContext::new());
    let q = r#"
        query {
            c1: cult(id: 1) {
              id
              name
            }
            c2: cult(id: 2) {
              id
              name
            }
            c3: cult(id: 3) {
              id
              name
            }
            persons {
              id
              name
              cult {
                id
                name
              }
              c1: cultById(id: 4) {
                id
                name
              }
              c2: cultById(id: 5) {
                id
                name
              }
              c3: cultById(id: 6) {
                id
                name
              }
            }
        }"#;
    let f = schema.query(&q).execute();
    let _r = block_on(f).unwrap();
}