Skip to content

Instantly share code, notes, and snippets.

@kevboutin
Last active June 20, 2024 05:16
Show Gist options
  • Save kevboutin/74437002ffd9fcceed48189efc991ee9 to your computer and use it in GitHub Desktop.
Save kevboutin/74437002ffd9fcceed48189efc991ee9 to your computer and use it in GitHub Desktop.
The DatabaseCache class
const DatabaseService = require('./databaseService');
/**
* Database options.
* @typedef {Object.<string, boolean|number|string>} DatabaseOptions
*/
/**
* A cache entry.
* @typedef {Object} CacheEntry
* @property {!number} expiration The expiration as an epoch timestamp.
* @property {DatabaseService} service The DatabaseService.
*/
/**
* @class DatabaseCache
*/
class DatabaseCache {
/**
* Creates a cache.
*
* @constructor
* @param [number] cacheTtl The time-to-live in seconds. Currently defaults to one hour.
*/
constructor(cacheTtl = 3600) {
/**
* The cache.
* @type {Object.<string, CacheEntry>}
* @public
*/
this.cache = {};
/**
* Cache time-to-live in milliseconds.
* @type {!number}
* @public
*/
this.cacheTtl = cacheTtl * 1000;
}
/**
* Determine if an unexpired cached database service exists.
*
* @param {string} cacheId The cache identifier.
* @returns {boolean} True if the cached database exists.
*/
cacheExists(cacheId) {
if (this.isCacheExpired(cacheId)) return false;
return this.cache[cacheId] ? true : false;
}
/**
* Get a cached DatabaseService or create a new one if it does not exist yet or it is expired.
*
* @param {string} cacheId The cache identifier.
* @param {DatabaseOptions} dbArgs Database settings to be passed to DatabaseService when creating new connections.
* @returns {DatabaseService} the cached DatabaseService object.
*/
getCache(cacheId, dbArgs) {
// This will return true if the cache does not exist.
if (this.isCacheExpired(cacheId)) {
// Remove the cache if it does exist as we know it is expired.
if (this.cache[cacheId]) {
this.removeCache(cacheId);
}
const service = new DatabaseService(dbArgs);
/** @constant {CacheEntry} */
const obj = {
expiration: Date.now() + this.cacheTtl,
service: service,
};
this.cache[cacheId] = obj;
}
return this.cache[cacheId].service;
}
/**
* Get the keys of the cache.
*
* @returns {Array<string>} An Array consisting of all the cache keys.
*/
getCacheKeys() {
return Object.keys(this.cache);
}
/**
* Get the size of the cache.
*
* @returns {number} The number of cache entries.
*/
getCacheSize() {
return Object.keys(this.cache).length;
}
/**
* Get the cached database service.
*
* @param {string} cacheId The cache identifier.
* @param {DatabaseOptions} dbArgs Database settings to be passed to DatabaseService when creating new connections.
* @returns {DatabaseService} the cached DatabaseService object.
*/
getService(cacheId, dbArgs) {
const cache = this.getCache(cacheId, dbArgs);
return cache;
}
/**
* Determines if the cache entry has expired.
*
* @param {string} cacheId The cache identifier.
* @return {boolean} True if expired.
*/
isCacheExpired(cacheId) {
if (!this.cache[cacheId] || !this.cache[cacheId].service) return true;
return this.cache[cacheId] && this.cache[cacheId].service && this.cache[cacheId].expiration < Date.now();
}
/**
* Removes a cache entry.
*
* @param {string} cacheId The cache identifier.
*/
removeCache(cacheId) {
delete this.cache[cacheId];
}
}
module.exports = DatabaseCache;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment