UNPKG

layered-loader

Version:

Data loader with support for caching and fallback data sources

132 lines 5.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AbstractFlatCache = void 0; const AbstractCache_1 = require("./AbstractCache"); class AbstractFlatCache extends AbstractCache_1.AbstractCache { isGroupCache() { return false; } getInMemoryOnly(loadParams) { const key = this.cacheKeyFromLoadParamsResolver(loadParams); if (this.inMemoryCache.ttlLeftBeforeRefreshInMsecs && !this.runningLoads.has(key)) { const expirationTime = this.inMemoryCache.getExpirationTime(key); if (expirationTime && expirationTime - Date.now() < this.inMemoryCache.ttlLeftBeforeRefreshInMsecs) { void this.getAsyncOnly(loadParams); } } return this.inMemoryCache.get(key); } getManyInMemoryOnly(keys) { // Note that it doesn't support preemptive refresh return this.inMemoryCache.getMany(keys); } getAsyncOnly(loadParams) { const key = this.cacheKeyFromLoadParamsResolver(loadParams); const existingLoad = this.runningLoads.get(key); if (existingLoad) { return existingLoad; } const loadingPromise = this.resolveValue(key, loadParams); this.runningLoads.set(key, loadingPromise); loadingPromise .then((resolvedValue) => { if (resolvedValue !== undefined) { this.inMemoryCache.set(key, resolvedValue); } this.runningLoads.delete(key); }) .catch(() => { this.runningLoads.delete(key); }); return loadingPromise; } getManyAsyncOnly(keys, loadParams) { // This doesn't support deduplication, and never might, as that would affect perf strongly. Maybe as an opt-in option in the future? const loadingPromise = this.resolveManyValues(keys, loadParams); return loadingPromise.then((result) => { for (let i = 0; i < result.resolvedValues.length; i++) { const resolvedValue = result.resolvedValues[i]; const id = this.cacheKeyFromValueResolver(resolvedValue); this.inMemoryCache.set(id, resolvedValue); } return result; }); } get(loadParams) { const inMemoryValue = this.getInMemoryOnly(loadParams); if (inMemoryValue !== undefined) { return Promise.resolve(inMemoryValue); } return this.getAsyncOnly(loadParams); } getMany(keys, loadParams) { const inMemoryValues = this.getManyInMemoryOnly(keys); // everything is in memory, hurray if (inMemoryValues.unresolvedKeys.length === 0) { return Promise.resolve(inMemoryValues.resolvedValues); } return this.getManyAsyncOnly(inMemoryValues.unresolvedKeys, loadParams).then((asyncRetrievedValues) => { return [...inMemoryValues.resolvedValues, ...asyncRetrievedValues.resolvedValues]; }); } async resolveValue(key, _loadParams) { if (this.asyncCache) { const cachedValue = await this.asyncCache.get(key).catch((err) => { this.loadErrorHandler(err, key, this.asyncCache, this.logger); }); if (cachedValue !== undefined) { return cachedValue; } } return undefined; } async resolveManyValues(keys, _loadParams) { if (this.asyncCache) { return this.asyncCache.getMany(keys).catch((err) => { this.loadErrorHandler(err, keys.toString(), this.asyncCache, this.logger); return { unresolvedKeys: keys, resolvedValues: [], }; }); } return { unresolvedKeys: keys, resolvedValues: [], }; } async invalidateCacheFor(key) { this.inMemoryCache.delete(key); if (this.asyncCache) { await this.asyncCache.delete(key).catch((err) => { this.cacheUpdateErrorHandler(err, undefined, this.asyncCache, this.logger); }); } this.runningLoads.delete(key); if (this.notificationPublisher) { this.notificationPublisher.delete(key).catch((err) => { this.notificationPublisher.errorHandler(err, this.notificationPublisher.channel, this.logger); }); } } async invalidateCacheForMany(keys) { if (this.asyncCache) { await this.asyncCache.deleteMany(keys).catch((err) => { /* c8 ignore next 1 */ this.cacheUpdateErrorHandler(err, undefined, this.asyncCache, this.logger); }); } for (let i = 0; i < keys.length; i++) { this.inMemoryCache.delete(keys[i]); this.runningLoads.delete(keys[i]); } if (this.notificationPublisher) { this.notificationPublisher.deleteMany(keys).catch((err) => { /* c8 ignore next 1 */ this.notificationPublisher.errorHandler(err, this.notificationPublisher.channel, this.logger); }); } } } exports.AbstractFlatCache = AbstractFlatCache; //# sourceMappingURL=AbstractFlatCache.js.map