@melchyore/adonis-cache
Version:
Cache package for AdonisJS V5
235 lines (234 loc) • 8.07 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@poppinss/utils");
const helpers_1 = require("@poppinss/utils/build/helpers");
const CacheEvent_1 = __importDefault(require("./Events/CacheEvent"));
const CacheMissed_1 = __importDefault(require("./Events/CacheMissed"));
const CacheKeyWritten_1 = __importDefault(require("./Events/CacheKeyWritten"));
const CacheKeyForgotten_1 = __importDefault(require("./Events/CacheKeyForgotten"));
const CacheHit_1 = __importDefault(require("./Events/CacheHit"));
const Utils_1 = __importDefault(require("./Utils"));
/**
* Repository class that will call the appropriate
* store methods.
*
* @export
* @class Repository
* @implements {RepositoryContract<CacheStoreContract>}
*/
class Repository {
constructor(_store, prefix) {
this._store = _store;
this.prefix = prefix;
}
get config() {
return this._config;
}
get driverConfig() {
return this._driverConfig;
}
get getTTL() {
return this._config.ttl || Repository.DEFAULT_TTL;
}
get store() {
return this._store;
}
setConfig(config, driverConfig) {
this._config = config;
this._driverConfig = driverConfig;
this._store.setPrefix(this.prefix);
}
setEventDispatcher(_emitter) {
this.event = _emitter;
this.emitter = new CacheEvent_1.default(this._config, _emitter);
}
async get(key, fallback) {
let value = await this._store.get(await this.itemKey(key));
if (this.isNull(value)) {
this.emitter.emit(new CacheMissed_1.default(key));
if (fallback) {
value = await this.resolveFallback(fallback);
}
}
else {
this.emitter.emit(new CacheHit_1.default(key, value));
}
return value;
}
async many(keys) {
const records = await this._store.many(keys);
for (const [key, value] of Object.entries(records)) {
if (this.isNull(value)) {
this.emitter.emit(new CacheMissed_1.default(key));
}
else {
this.emitter.emit(new CacheHit_1.default(key, value));
}
}
return records;
}
async has(key) {
return (await this._store.has(await this.itemKey(key))) === true;
}
async missing(key) {
return !(await this.has(key));
}
async pull(key) {
const value = await this.get(key);
if (!this.isNull(value)) {
await this.forget(key);
}
return value;
}
async put(key, value, ttl) {
const expiration = this.calculateTTL(ttl);
const result = await this._store.put(await this.itemKey(key), value, expiration);
if (result) {
this.emitter.emit(new CacheKeyWritten_1.default(key, value, expiration));
}
return result;
}
async add(key, value, ttl) {
if (typeof this._store['add'] === 'function') {
const expiration = this.calculateTTL(ttl);
const result = await this._store.add(await this.itemKey(key), value, expiration);
if (result) {
this.emitter.emit(new CacheKeyWritten_1.default(key, value, expiration));
}
return result;
}
const cachedValue = await this.get(key);
if (this.isNull(cachedValue)) {
return await this.put(key, value, ttl);
}
return false;
}
async set(key, value, ttl) {
return await this.put(key, value, ttl);
}
async increment(key, value = 1) {
return await this._store.increment(await this.itemKey(key), value);
}
async decrement(key, value = 1) {
return await this._store.decrement(await this.itemKey(key), value);
}
async putMany(list, ttl) {
const expiration = this.calculateTTL(ttl);
const results = await this._store.putMany(list, expiration);
let result = {};
for (let i = 0; i < results.length; ++i) {
const key = Object.keys(list)[i];
if (results[i] === true) {
result[key] = true;
this.emitter.emit(new CacheKeyWritten_1.default(key, Object.values(list)[i], expiration));
}
else {
result[key] = false;
}
}
return result;
}
async putManyForever(list) {
const results = await this._store.putManyForever(list);
let result = {};
for (let i = 0; i < results.length; ++i) {
const key = Object.keys(list)[i];
if (results[i] === true) {
result[key] = true;
this.emitter.emit(new CacheKeyWritten_1.default(key, Object.values(list)[i], 0));
}
else {
result[key] = false;
}
}
return result;
}
async forever(key, value) {
return await this._store.forever(await this.itemKey(key), value);
}
async forget(key) {
const result = await this._store.forget(await this.itemKey(key));
if (result) {
this.emitter.emit(new CacheKeyForgotten_1.default(key));
}
return result;
}
async forgetMultiple(keys) {
let result = {};
for (const key of keys) {
result[key] = await this.forget(key);
}
return result;
}
async remember(key, ttl, closure) {
if (this.checkClosure(closure)) {
let value = await this.get(key);
if (!this.isNull(value)) {
return value;
}
value = await closure();
await this.put(key, value, ttl);
return value;
}
}
async sear(key, closure) {
return await this.rememberForever(key, closure);
}
async rememberForever(key, closure) {
if (this.checkClosure(closure)) {
let value = await this.get(key);
if (!this.isNull(value)) {
return value;
}
value = await closure();
await this.forever(key, value);
return value;
}
}
async flush() {
return await this._store.flush();
}
async clear() {
return await this.flush();
}
tags(names) {
if (!('tags' in this._store)) {
throw new utils_1.Exception('This cache store does not support tagging');
}
const taggedCache = this._store.tags(Array.isArray(names) ? names : [names]);
taggedCache.setConfig(this._config, this._driverConfig);
taggedCache.setEventDispatcher(this.event);
return taggedCache;
}
async itemKey(key) {
return key;
}
calculateTTL(ttl) {
if (ttl && ttl < 0) {
throw new utils_1.Exception('Expiration time (TTL) cannot be negative');
}
const ttlInMilliseconds = Number(helpers_1.string.toMs(`${ttl ?? this.getTTL}s`));
return this._store.calculateTTL(ttlInMilliseconds);
}
checkClosure(closure) {
if (!Utils_1.default.isFunction(closure)) {
throw new utils_1.Exception('Closure must be a function');
}
return true;
}
isNull(value) {
return value === null || value === undefined;
}
async resolveFallback(fallback) {
let fallbackValue = Utils_1.default.isFunction(fallback) ? await fallback() : fallback;
return fallbackValue;
}
}
exports.default = Repository;
/*
* Default expiration time `ttl` = 1 hour expressed in seconds.
*/
Repository.DEFAULT_TTL = 60 * 60;