moleculer
Version:
Fast & powerful microservices framework for Node.JS
192 lines (168 loc) • 3.8 kB
JavaScript
/*
* moleculer
* Copyright (c) 2017 Ice Services (https://github.com/ice-services/moleculer)
* MIT Licensed
*/
"use strict";
//const Promise = require("bluebird");
const _ = require("lodash");
const { hash } = require("node-object-hash")({ sort: false, coerce: false});
/**
* Abstract cacher class
*
* @class Cacher
*/
class Cacher {
/**
* Creates an instance of Cacher.
*
* @param {object} opts
*
* @memberOf Cacher
*/
constructor(opts) {
this.opts = _.defaultsDeep(opts, {
prefix: "",
ttl: null
});
this.prefix = this.opts.prefix;
}
/**
* Initialize cacher
*
* @param {any} broker
*
* @memberOf Cacher
*/
init(broker) {
this.broker = broker;
if (this.broker) {
this.logger = broker.getLogger("CACHER");
broker.use(this.middleware());
this.broker.on("cache.clean", payload => {
if (Array.isArray(payload))
payload.forEach(match => this.clean(match));
else
this.clean(payload);
});
this.broker.on("cache.del", payload => {
if (Array.isArray(payload))
payload.forEach(key => this.del(key));
else
this.del(payload);
});
}
}
/**
* Close cacher
*
* @memberOf Cacher
*/
close() {
}
/**
* Get a cached content by key
*
* @param {any} key
*
* @memberOf Cacher
*/
get(/*key*/) {
/* istanbul ignore next */
throw new Error("Not implemented method!");
}
/**
* Set a content by key to cache
*
* @param {any} key
* @param {any} data
*
* @memberOf Cacher
*/
set(/*key, data*/) {
/* istanbul ignore next */
throw new Error("Not implemented method!");
}
/**
* Delete a content by key from cache
*
* @param {any} key
*
* @memberOf Cacher
*/
del(/*key*/) {
/* istanbul ignore next */
throw new Error("Not implemented method!");
}
/**
* Clean cache. Remove every key by match
* @param {any} match string. Default is "**"
* @returns {Promise}
*
* @memberOf Cacher
*/
clean(/*match = "**"*/) {
/* istanbul ignore next */
throw new Error("Not implemented method!");
}
/**
* Get a cache key by name and params.
* Concatenate the name and the hashed params object
*
* @param {String} name
* @param {Object} params
* @param {Array|null} keys
* @returns
*/
getCacheKey(name, params, keys) {
if (params) {
const keyPrefix = name + ":";
if (keys) {
if (keys.length == 1) {
// Quick solution for ['id'] only key
const val = _.get(params, keys[0]);
return keyPrefix + (_.isObject(val) ? hash(val) : val);
}
if (keys.length > 0) {
return keys.reduce((a, key, i) => {
const val = _.get(params, key);
return a + (i ? "|" : "") + (_.isObject(val) ? hash(val) : val);
}, keyPrefix);
}
}
else {
return keyPrefix + hash(params);
}
}
return name;
}
/**
* Register cacher as a middleware
*
* @memberOf Cacher
*/
middleware() {
return (handler, action) => {
if (action.cache) {
return function cacherMiddleware(ctx) {
const cacheKey = this.getCacheKey(action.name, ctx.params, action.cache.keys);
return this.get(cacheKey).then(content => {
if (content != null) {
// Found in the cache! Don't call handler, return with the context
ctx.cachedResult = true;
return content;
}
// Call the handler
return handler(ctx).then(result => {
// Save the response to the cache
this.set(cacheKey, result);
return result;
});
});
}.bind(this);
}
return handler;
};
}
}
module.exports = Cacher;