js/cache/cache_manager.js
// NPM IMPORTS
import assert from 'assert'
// COMMON IMPORTS
import T from '../utils/types'
/**
* Contextual constant for this file logs.
* @private
*/
const context = 'common/cache/cache_manager'
/**
* Cache manager class.
*
* @author Luc BORIES
* @license Apache-2.0
*
* @example
* API:
* get(arg_key:string, arg_default):Promise
* mget(arg_keys:array, arg_default:any|array):Promise
* has(arg_key:string):Promise
* set(arg_key:string, arg_value, arg_ttl=undefined):Promise
* set_ttl(arg_key:string, arg_ttl):Promise
* get_ttl(arg_key:string):Promise
* get_keys():Promise
* remove(arg_key:string|array):Promise
* flush():nothing - delete all entries.
* close():nothing - clear interval timeout for checks.
*
* add_adapter(arg_cache_adapter):nothing - add a cache adapters.
*
*/
export default class CacheManager
{
/**
* Create Cache instance to manage cached datas.
*
* @param {array} arg_cache_adapters - cache adapters.
*
* @returns {nothing}
*/
constructor(arg_cache_adapters=[])
{
assert( T.isArray(arg_cache_adapters), context + ':constructor:bad cache adapters array')
/**
* Class type flag.
* @type {boolean}
*/
this.is_cache_manager = true
/**
* Cache adapters array.
* @type {array}
*/
this._cache_adapters = arg_cache_adapters
}
/**
* Get a cached value.
*
* @param {string} arg_key - key string to retrieve the value.
* @param {any} arg_default - returned default value if the key is not found (optional) (default:undefined).
*
* @returns {Promise} - Promise of cached value or undefined.
*/
get(arg_key, arg_default=undefined)
{
if (this._cache_adapters.length == 0)
{
return Promise.resolve(arg_default)
}
if (this._cache_adapters.length == 1)
{
return this._cache_adapters[0].get(arg_key, arg_default)
}
let promises = []
this._cache_adapters.forEach(
(adapter)=>{
return adapter.get(arg_key, arg_default)
}
)
return Promise.race(promises)
}
/**
* Get a cached value.
*
* @param {array} arg_keys - key strings to retrieve the values.
* @param {any} arg_default - returned default value if the key is not found (optional) (default:undefined).
*
* @returns {Promise} - Promise of cached value or undefined array.
*/
mget(arg_keys, arg_default=undefined)
{
if (this._cache_adapters.length == 0)
{
return Promise.resolve([arg_default])
}
if (this._cache_adapters.length == 1)
{
return this._cache_adapters[0].mget(arg_keys, arg_default)
}
let promises = []
this._cache_adapters.forEach(
(adapter)=>{
promises.push( adapter.mget(arg_keys, arg_default) )
}
)
return Promise.race(promises)
}
/**
* Test if given key has a cached value.
*
* @param {string} arg_key - key string to retrieve the value.
*
* @returns {Promise} - Promise of cached value or undefined.
*/
has(arg_key)
{
if (this._cache_adapters.length == 0)
{
return Promise.resolve(false)
}
if (this._cache_adapters.length == 1)
{
return this._cache_adapters[0].has(arg_key)
}
let promises = []
this._cache_adapters.forEach(
(adapter)=>{
promises.push( adapter.has(arg_key) )
}
)
return Promise.race(promises)
}
/**
* Set a cached value with given key.
*
* @param {string} arg_key - key string to retrieve the value.
* @param {any} arg_value - value to cache.
* @param {integer} arg_ttl - time to leave for cached value.
*
* @returns {Promise} - Promise of nothing.
*/
set(arg_key, arg_value, arg_ttl=undefined)
{
if (this._cache_adapters.length == 0)
{
return Promise.resolve()
}
if (this._cache_adapters.length == 1)
{
return this._cache_adapters[0].set(arg_key, arg_value, arg_ttl)
}
let promises = []
this._cache_adapters.forEach(
(adapter)=>{
promises.push( adapter.set(arg_key, arg_value, arg_ttl) )
}
)
return Promise.all(promises)
}
/**
* Set cached value ttl.
*
* @param {string} arg_key - key string to retrieve the value.
* @param {integer} arg_ttl - time to leave for cached value.
*
* @returns {Promise} - Promise of nothing.
*/
set_ttl(arg_key, arg_ttl)
{
if (this._cache_adapters.length == 0)
{
return Promise.resolve()
}
if (this._cache_adapters.length == 1)
{
return this._cache_adapters[0].set_ttl(arg_key, arg_ttl)
}
let promises = []
this._cache_adapters.forEach(
(adapter)=>{
promises.push( adapter.set_ttl(arg_key, arg_ttl) )
}
)
return Promise.all(promises)
}
/**
* Get cached value ttl.
*
* @param {string} arg_key - key string to retrieve the value.
*
* @returns {Promise} - Promise of integer|undefined.
*/
get_ttl(arg_key)
{
if (this._cache_adapters.length == 0)
{
return Promise.resolve()
}
if (this._cache_adapters.length == 1)
{
return this._cache_adapters[0].get_ttl(arg_key)
}
let promises = []
this._cache_adapters.forEach(
(adapter)=>{
promises.push( adapter.get_ttl(arg_key) )
}
)
return Promise.race(promises)
}
/**
* Get cached keys.
*
* @returns {Promise} - Promise of keys array.
*/
get_keys()
{
if (this._cache_adapters.length == 0)
{
return Promise.resolve([])
}
if (this._cache_adapters.length == 1)
{
return this._cache_adapters[0].get_keys()
}
let promises = []
this._cache_adapters.forEach(
(adapter)=>{
promises.push( adapter.get_keys() )
}
)
return Promise.race(promises)
}
/**
* Remove a cached value.
*
* @param {string|array} arg_keys - value key string or array.
*
* @returns {Promise} - Promise of undefined.
*/
remove(arg_keys)
{
if (this._cache_adapters.length == 0)
{
return Promise.resolve()
}
if (this._cache_adapters.length == 1)
{
return this._cache_adapters[0].remove(arg_keys)
}
let promises = []
this._cache_adapters.forEach(
(adapter)=>{
promises.push( adapter.remove(arg_keys) )
}
)
return Promise.all(promises)
}
/**
* Flush all cached values (clear interval timeout for checks).
*
* @returns {Promise} - Promise of undefined.
*/
flush()
{
if (this._cache_adapters.length == 0)
{
return Promise.resolve()
}
if (this._cache_adapters.length == 1)
{
return this._cache_adapters[0].flush()
}
let promises = []
this._cache_adapters.forEach(
(adapter)=>{
promises.push( adapter.flush() )
}
)
return Promise.all(promises)
}
/**
* Close cache engine.
*
* @returns {Promise} - Promise of undefined.
*/
close()
{
if (this._cache_adapters.length == 0)
{
return Promise.resolve()
}
if (this._cache_adapters.length == 1)
{
return this._cache_adapters[0].close()
}
let promises = []
this._cache_adapters.forEach(
(adapter)=>{
promises.push( adapter.close() )
}
)
return Promise.all(promises)
}
/**
* Add a cache adapter.
*
* @param{DataCacheAdapter} arg_cache_adapter - cache adapter.
*
* @returns {nothing}
*/
add_adapter(arg_cache_adapter)
{
assert( T.isObject(arg_cache_adapter) && arg_cache_adapter.is_cache_adapter, context + ':add_adapter:bad cache adapters array')
this._cache_adapters.push(arg_cache_adapter)
}
}