mastercache
Version:
Multi-tier cache module for Node.js. Redis, Upstash, CloudfareKV, File, in-memory and others drivers
234 lines (231 loc) • 6.67 kB
JavaScript
// ../../node_modules/.pnpm/hexoid@2.0.0/node_modules/hexoid/dist/index.mjs
for (r = 256, n = []; r--; ) n[r] = (r + 256).toString(16).substring(1);
var r;
var n;
function hexoid(r) {
r = r || 16;
var t = "", o = 0;
return function() {
if (!t || 256 === o) {
for (t = "", o = (1 + r) / 2 | 0; o--; ) t += n[256 * Math.random() | 0];
t = t.substring(o = 0, r - 2);
}
return t + n[o++];
};
}
// ../../node_modules/.pnpm/@lukeed+ms@2.0.2/node_modules/@lukeed/ms/dist/index.mjs
var RGX = /^(-?(?:\d+)?\.?\d+) *(m(?:illiseconds?|s(?:ecs?)?))?(s(?:ec(?:onds?|s)?)?)?(m(?:in(?:utes?|s)?)?)?(h(?:ours?|rs?)?)?(d(?:ays?)?)?(w(?:eeks?|ks?)?)?(y(?:ears?|rs?)?)?$/;
var SEC = 1e3;
var MIN = SEC * 60;
var HOUR = MIN * 60;
var DAY = HOUR * 24;
var YEAR = DAY * 365.25;
function parse(val) {
var num, arr = val.toLowerCase().match(RGX);
if (arr != null && (num = parseFloat(arr[1]))) {
if (arr[3] != null) return num * SEC;
if (arr[4] != null) return num * MIN;
if (arr[5] != null) return num * HOUR;
if (arr[6] != null) return num * DAY;
if (arr[7] != null) return num * DAY * 7;
if (arr[8] != null) return num * YEAR;
return num;
}
}
// src/helpers.ts
function resolveTtl(ttl, defaultTtl = 3e4) {
if (typeof ttl === "number") return ttl;
if (ttl === null) {
return void 0;
}
if (ttl === void 0) {
if (typeof defaultTtl === "number") return defaultTtl;
if (typeof defaultTtl === "string") return parse(defaultTtl);
return void 0;
}
return parse(ttl);
}
// src/cache/cache-entry/cache-entry-options.ts
var toId = hexoid(12);
var CacheEntryOptions = class _CacheEntryOptions {
/**
* The options that were passed to the constructor
*/
#options;
/**
* Unique identifier that will be used when logging
* debug information.
*/
id;
/**
* Logical TTL is when the value is considered expired
* but still can be in the cache ( Grace period )
*/
logicalTtl;
/**
* Physical TTL is the time when value will be automatically
* removed from the cache. This is the Grace period
* duration
*/
physicalTtl;
/**
* Early expiration TTL is when the value should be
* refreshed in the background.
*/
earlyExpireTtl;
/**
* Timeouts for the cache operations
*/
timeouts;
/**
* Resolved grace period options
*/
gracePeriod;
/**
* Max time to wait for the lock to be acquired
*/
lockTimeout;
constructor(options = {}, defaults = {}) {
this.id = toId();
const timeouts = { ...defaults.timeouts, ...options.timeouts };
this.#options = {
...defaults,
...options,
gracePeriod: { ...defaults.gracePeriod, ...options.gracePeriod },
timeouts: Object.keys(timeouts).length ? timeouts : void 0
};
this.logicalTtl = this.#resolveLogicalTtl();
this.physicalTtl = this.#resolvePhysicalTtl();
this.earlyExpireTtl = this.#resolveEarlyExpireTtl();
this.timeouts = this.#resolveTimeouts();
this.gracePeriod = this.#resolveGracePeriod();
this.lockTimeout = resolveTtl(this.#options.lockTimeout, null);
}
/**
* Resolve the grace period options
*/
#resolveGracePeriod() {
if (!this.#options.gracePeriod || !this.#options.gracePeriod.enabled) {
return { enabled: false };
}
return {
enabled: true,
duration: resolveTtl(this.#options.gracePeriod.duration),
fallbackDuration: resolveTtl(this.#options.gracePeriod.fallbackDuration)
};
}
/**
* Resolve the timeouts to a duration in milliseconds
*/
#resolveTimeouts() {
const timeouts = this.#options.timeouts;
if (!timeouts) return void 0;
return {
soft: resolveTtl(timeouts.soft, null),
hard: resolveTtl(timeouts.hard, null)
};
}
/**
* Early expiration is received as a percentage of the
* logical TTL. We need to convert it to a duration
* in milliseconds.
*/
#resolveEarlyExpireTtl() {
const percentage = this.#options.earlyExpiration;
if (!percentage || percentage <= 0 || percentage >= 1) {
return void 0;
}
if (!this.logicalTtl) return void 0;
return this.logicalTtl * percentage;
}
/**
* Returns a new instance of `CacheItemOptions` with the same
* options as the current instance, but with any provided
* options overriding the current
*
* For performance reasons, if no options are provided, the
* current instance is returned
*/
cloneWith(options) {
return options ? new _CacheEntryOptions(options, this.#options) : this;
}
/**
* Resolve the logical TTL to a duration in milliseconds
*/
#resolveLogicalTtl() {
return resolveTtl(this.#options.ttl);
}
/**
* Resolve the physical TTL to a duration in milliseconds
*
* If grace period is not enabled then the physical TTL
* is the same as the logical TTL
*/
#resolvePhysicalTtl() {
return this.isGracePeriodEnabled ? resolveTtl(this.#options.gracePeriod.duration) : this.logicalTtl;
}
get isGracePeriodEnabled() {
return this.#options.gracePeriod?.enabled;
}
get suppressL2Errors() {
return this.#options.suppressL2Errors;
}
/**
* Set a new logical TTL
*/
setLogicalTtl(ttl) {
this.#options.ttl = ttl;
this.logicalTtl = this.#resolveLogicalTtl();
this.physicalTtl = this.#resolvePhysicalTtl();
this.earlyExpireTtl = this.#resolveEarlyExpireTtl();
return this;
}
/**
* Compute the logical TTL timestamp from now
*/
logicalTtlFromNow() {
if (!this.logicalTtl) return void 0;
return Date.now() + this.logicalTtl;
}
/**
* Compute the physical TTL timestamp from now
*/
physicalTtlFromNow() {
if (!this.physicalTtl) return void 0;
return Date.now() + this.physicalTtl;
}
/**
* Compute the early expiration TTL timestamp from now
*/
earlyExpireTtlFromNow() {
if (!this.earlyExpireTtl) return void 0;
return Date.now() + this.earlyExpireTtl;
}
/**
* Compute the lock timeout we should use for the
* factory
*/
factoryTimeout(hasFallbackValue) {
if (!this.timeouts) return void 0;
if (hasFallbackValue && this.isGracePeriodEnabled && this.timeouts.soft) {
return this.timeouts.soft;
}
return this.timeouts.hard;
}
/**
* Compute the maximum time we should wait for the
* lock to be acquired
*/
getApplicableLockTimeout(hasFallbackValue) {
if (this.lockTimeout) {
return this.lockTimeout;
}
if (hasFallbackValue && this.isGracePeriodEnabled && this.timeouts?.soft) {
return this.timeouts.soft;
}
}
};
export {
CacheEntryOptions
};
//# sourceMappingURL=cache-entry-options.js.map