1 unstable release

Uses new Rust 2024

new 0.1.0 May 18, 2025

#123 in Caching

MIT/Apache

34KB
730 lines

Versatile Dataloader

A dataloader (originally developed by facebook) allows to batch requests coming in at roughly the same time. This is useful e.g., to avoid the n+1 problem in GraphQL.

Forked/extracted from async-graphql as it has no dependencies towards async-graphql and might be useful on its own.

Example

use std::collections::{HashSet, HashMap};
use std::convert::Infallible;
use versatile_dataloader::{Loader, DataLoader};

/// This loader simply converts the integer key into a string value.
struct MyLoader;

impl Loader<i32, String> for MyLoader {
    type Error = Infallible;

    async fn load(&self, keys: &[i32]) -> Result<HashMap<i32, String>, Self::Error> {
        // Implement database access or similar here.
        Ok(keys.iter().copied().map(|n| (n, n.to_string())).collect())
    }
}


tokio::runtime::Builder::new_current_thread().build().unwrap().block_on(async {

// Load data with dataloader:
let loader = DataLoader::new(MyLoader, tokio::spawn);
let strings = vec![loader.load_one(1).await.unwrap(), loader.load_one(2).await.unwrap(), loader.load_one(3).await.unwrap()];
// The dataloader load function is only called once.

assert_eq!(strings, vec![Some("1".to_string()), Some("2".to_string()), Some("3".to_string())]);

});
  • async-graphql includes a dataloder where this one is based on. We adapted the API to make the return type generic rather than an associated type. This allows to use one struct as a dataloader for different return types all with the same key (e.g., a UUID).
  • dataloader-rs is similar, but it has a less versatile API that does not support errors.

License

Licensed under either of

Dependencies

~3.5–10MB
~88K SLoC