graphql / dataloader

DataLoader is a generic utility to be used as part of your application's data fetching layer to provide a consistent API over various backends and reduce requests to those backends via batching and caching.
MIT License
12.89k stars 515 forks source link

Add support for asynchronous cacheMap #24

Closed stanogurnik closed 8 years ago

stanogurnik commented 8 years ago

When dealing with large datasets it would be nice to be able to use also other cache drivers as Redis, memcache etc. as it could be too much for just memory storage, so DataLoader should be able to handle Promise specifically when using get() to retrieve cached Promise on cacheMap ...

vieks commented 8 years ago

This is exactly the issue I have created #23 but I auto-closed it because it's silly.

The purpose of Dataloader is to prevent at most round trips generated by a data source (Redis, PostgreSQL, whatever...) induced by their network nature. So permitting to create a async remote cache goes against the benefit of using Dataloader hence becoming useless.

Strictly speaking Dataloader doesn't realy implement a cache but a memoize mechanism.

Furthermore, if you look at the source: _promiseCache: CacheMap<K, Promise<V>>; Dataloader memoize/cache Promise objects, no pure raw data types, so you can't serialize them into a remote cache.

If you want a real cache in front of a slow data source/store/base, make it in an upstream batch function.

as it could be too much for just memory storage

Or at least use the custom cache api with an in-memory LRU local cache:

LRU node LRU memoize

stanogurnik commented 8 years ago

@vieks it makes sense in how you put it, thank you for explanation & closing issue.

leebyron commented 8 years ago

@vieks is correct here. DataLoader's cache is purely a local (in memory per instance) cache. It is not a distributed cache like memcached.

Here is a rough example of how you might implement a "read through" distributed cache with DataLoader:

function loadValue(id) {
  return fastLoader.load(id).catch(err => slowLoader.load(id));
}

let fastLoader = new DataLoader(ids => batchLoadFromMemcache(ids));

let slowLoader = new DataLoader(ids => batchLoadFromSQL(ids).then(values => {
  writeToMemcache(ids, values); // fire and forget
  return values;
}));
eugenehp commented 8 years ago

Hey Lee, @leebyron

Do you think this concept could be used on the level of the internal Cache Storage?

Thanks.