async_graphql_dataloader/
loader.rs1use crate::batcher::Batcher;
3use crate::cache::Cache;
4use crate::error::DataLoaderError;
5use async_trait::async_trait;
6use std::collections::HashMap;
7
8#[async_trait]
9pub trait BatchLoad: Send + Sync {
10 type Key: Send + Sync + Clone + Eq + std::hash::Hash + std::fmt::Debug + 'static;
11 type Value: Send + Sync + Clone + 'static;
12 type Error: Send + Sync + From<String> + std::fmt::Display + 'static;
13
14 async fn load(
15 &self,
16 keys: &[Self::Key],
17 ) -> HashMap<Self::Key, Result<Self::Value, Self::Error>>;
18}
19
20pub struct DataLoader<L: BatchLoad> {
21 batcher: std::sync::Arc<Batcher<L>>,
22 cache: std::sync::Arc<Cache<L::Key, Result<L::Value, DataLoaderError>>>,
23 max_batch_size: usize,
24 delay: std::time::Duration,
25}
26
27impl<L> DataLoader<L>
28where
29 L: BatchLoad + 'static,
30 L::Key: Clone + Eq + std::hash::Hash + std::fmt::Debug,
31 L::Value: Clone,
32 L::Error: From<String> + std::fmt::Display,
33{
34 pub fn new(loader: L) -> Self {
35 let loader_arc = std::sync::Arc::new(loader);
36 let batcher = std::sync::Arc::new(Batcher::new(std::sync::Arc::clone(&loader_arc)));
37
38 Self {
39 batcher,
40 cache: std::sync::Arc::new(Cache::new()),
41 max_batch_size: 100,
42 delay: std::time::Duration::from_millis(10),
43 }
44 }
45
46 pub fn with_max_batch_size(mut self, size: usize) -> Self {
47 self.max_batch_size = size;
48 self
49 }
50
51 pub fn with_delay(mut self, delay: std::time::Duration) -> Self {
52 self.delay = delay;
53 self
54 }
55
56 pub async fn load(&self, key: L::Key) -> Result<L::Value, DataLoaderError> {
57 if let Some(cached) = self.cache.get(&key) {
59 return cached;
60 }
61
62 let result = self.batcher.schedule(key.clone()).await;
64
65 if let Ok(ref value) = result {
67 self.cache.set(key.clone(), Ok(value.clone()));
68 } else if let Err(ref error) = result {
69 self.cache.set(key.clone(), Err(error.clone()));
70 }
71
72 result
73 }
74
75 pub fn clear(&self) {
76 self.cache.clear();
77 }
78
79 pub fn prime(&self, key: L::Key, value: Result<L::Value, DataLoaderError>) {
80 self.cache.set(key, value);
81 }
82}
83
84impl<L> Clone for DataLoader<L>
85where
86 L: BatchLoad,
87{
88 fn clone(&self) -> Self {
89 Self {
90 batcher: std::sync::Arc::clone(&self.batcher),
91 cache: std::sync::Arc::clone(&self.cache),
92 max_batch_size: self.max_batch_size,
93 delay: self.delay,
94 }
95 }
96}