layered-loader
Version:
Data loader with support for caching and fallback data sources
105 lines • 4.13 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisCache = void 0;
const Loader_1 = require("../Loader");
const AbstractRedisCache_1 = require("./AbstractRedisCache");
const RedisExpirationTimeDataSource_1 = require("./RedisExpirationTimeDataSource");
class RedisCache extends AbstractRedisCache_1.AbstractRedisCache {
expirationTimeLoadingOperation;
ttlLeftBeforeRefreshInMsecs;
name = 'Redis cache';
constructor(redis, config = AbstractRedisCache_1.DEFAULT_REDIS_CACHE_CONFIGURATION) {
super(redis, config);
this.ttlLeftBeforeRefreshInMsecs = config.ttlLeftBeforeRefreshInMsecs;
if (!this.ttlLeftBeforeRefreshInMsecs && config.ttlCacheTtl) {
throw new Error('ttlCacheTtl cannot be specified if ttlLeftBeforeRefreshInMsecs is not.');
}
this.expirationTimeLoadingOperation = new Loader_1.Loader({
inMemoryCache: config.ttlCacheTtl
? {
cacheId: 'ttl-cache',
ttlInMsecs: config.ttlCacheTtl,
maxItems: config.ttlCacheSize ?? 500,
}
: undefined,
dataSources: [new RedisExpirationTimeDataSource_1.RedisExpirationTimeDataSource(this)],
});
}
delete(key) {
return this.redis.del(this.resolveKey(key));
}
deleteMany(keys) {
const processedKeys = keys.map((key) => {
return this.resolveKey(key);
});
return this.redis.del(processedKeys);
}
get(key) {
return this.redis.get(this.resolveKey(key)).then((redisResult) => {
return this.postprocessResult(redisResult);
});
}
getMany(keys) {
const transformedKeys = keys.map((entry) => this.resolveKey(entry));
const resolvedValues = [];
const unresolvedKeys = [];
return this.redis.mget(transformedKeys).then((redisResult) => {
for (let i = 0; i < keys.length; i++) {
const currentResult = redisResult[i];
if (currentResult !== null) {
resolvedValues.push(this.postprocessResult(currentResult));
}
else {
unresolvedKeys.push(keys[i]);
}
}
return {
resolvedValues,
unresolvedKeys,
};
});
}
getExpirationTime(key) {
const now = Date.now();
return this.redis.pttl(this.resolveKey(key)).then((remainingTtl) => {
return remainingTtl && remainingTtl > 0 ? now + remainingTtl : undefined;
});
}
set(key, value) {
return this.internalSet(this.resolveKey(key), value).then(() => {
if (this.ttlLeftBeforeRefreshInMsecs) {
void this.expirationTimeLoadingOperation.invalidateCacheFor(key);
}
});
}
setMany(entries) {
if (this.config.ttlInMsecs) {
const setCommands = [];
for (let i = 0; i < entries.length; i++) {
const entry = entries[i];
setCommands.push([
'set',
this.resolveKey(entry.key),
entry.value && this.config.json ? JSON.stringify(entry.value) : entry.value,
'PX',
this.config.ttlInMsecs,
]);
}
return this.redis.multi(setCommands).exec();
}
// No TTL set
const commandParam = [];
for (let i = 0; i < entries.length; i++) {
const entry = entries[i];
commandParam.push(this.resolveKey(entry.key));
commandParam.push(entry.value && this.config.json ? JSON.stringify(entry.value) : entry.value);
}
return this.redis.mset(commandParam);
}
async close() {
// prevent refreshes after everything is shutting down to prevent "Error: Connection is closed." errors
this.ttlLeftBeforeRefreshInMsecs = 0;
}
}
exports.RedisCache = RedisCache;
//# sourceMappingURL=RedisCache.js.map