UNPKG

6.49 kBJavaScriptView Raw
1/**
2 * @license
3 * MOST Web Framework 2.0 Codename Blueshift
4 * Copyright (c) 2017, THEMOST LP All rights reserved
5 *
6 * Use of this source code is governed by an BSD-3-Clause license that can be
7 * found in the LICENSE file at https://themost.io/license
8 */
9///
10var NodeCache = require('node-cache');
11var Q = require('q');
12var _ = require('lodash');
13var Symbol = require('symbol');
14var AbstractMethodError = require("../common/errors").AbstractMethodError;
15var AbstractClassError = require("../common/errors").AbstractClassError;
16var LangUtils = require('@themost/common/utils').LangUtils;
17var Args = require('@themost/common/utils').Args;
18var HttpApplicationService = require('./types').HttpApplicationService;
19
20/**
21 * @class
22 * @constructor
23 * @param {HttpApplication} app
24 * @augments HttpApplicationService
25 */
26function CacheStrategy(app) {
27 CacheStrategy.super_.bind(this)(app);
28 if (this.constructor === CacheStrategy.prototype.constructor) {
29 throw new AbstractClassError();
30 }
31}
32LangUtils.inherits(CacheStrategy, HttpApplicationService);
33
34/**
35 * Sets a key value pair in cache.
36 * @abstract
37 * @param {string} key - A string that represents the key of the cached value
38 * @param {*} value - The value to be cached
39 * @param {number=} absoluteExpiration - An absolute expiration time in seconds. This parameter is optional.
40 * @returns {Promise|*}
41 */
42// eslint-disable-next-line no-unused-vars
43CacheStrategy.prototype.add = function(key, value, absoluteExpiration) {
44 throw new AbstractMethodError();
45};
46
47/**
48 * Removes a cached value.
49 * @abstract
50 * @param {string} key - A string that represents the key of the cached value to be removed
51 * @returns {Promise|*}
52 */
53// eslint-disable-next-line no-unused-vars
54CacheStrategy.prototype.remove = function(key) {
55 throw new AbstractMethodError();
56};
57/**
58 * Flush all cached data.
59 * @abstract
60 * @returns {Promise|*}
61 */
62CacheStrategy.prototype.clear = function() {
63 throw new AbstractMethodError();
64};
65/**
66 * Gets a cached value defined by the given key.
67 * @param {string} key
68 * @returns {Promise|*}
69 */
70// eslint-disable-next-line no-unused-vars
71CacheStrategy.prototype.get = function(key) {
72 throw new AbstractMethodError();
73};
74/**
75 * Gets data from cache or executes the defined function and adds the result to the cache with the specified key
76 * @param {string|*} key - A string which represents the key of the cached data
77 * @param {Function} fn - A function to execute if data will not be found in cache
78 * @param {number=} absoluteExpiration - An absolute expiration time in seconds. This parameter is optional.
79 * @returns {Promise|*}
80 */
81// eslint-disable-next-line no-unused-vars
82CacheStrategy.prototype.getOrDefault = function(key, fn, absoluteExpiration) {
83 throw new AbstractMethodError();
84};
85
86var rawCacheProperty = Symbol('rawCache');
87var CACHE_ABSOLUTE_EXPIRATION = 0;
88
89/**
90 * Implements the cache for a data application.
91 * @class HttpCache
92 * @param {HttpApplication} app
93 * @constructor
94 */
95function DefaultCacheStrategy(app) {
96 DefaultCacheStrategy.super_.bind(this)(app);
97 //set absoluteExpiration (from application configuration)
98 var expiration = CACHE_ABSOLUTE_EXPIRATION;
99 var absoluteExpiration = LangUtils.parseInt(app.getConfiguration().getSourceAt('settings/cache/absoluteExpiration'));
100 if (absoluteExpiration>=0) {
101 expiration = absoluteExpiration;
102 }
103 this[rawCacheProperty] = new NodeCache( {
104 stdTTL:expiration
105 });
106}
107LangUtils.inherits(DefaultCacheStrategy, CacheStrategy);
108/**
109 * Sets a key value pair in cache.
110 * @abstract
111 * @param {string} key - A string that represents the key of the cached value
112 * @param {*} value - The value to be cached
113 * @param {number=} absoluteExpiration - An absolute expiration time in seconds. This parameter is optional.
114 * @returns {Promise|*}
115 */
116DefaultCacheStrategy.prototype.add = function(key, value, absoluteExpiration) {
117 var self = this;
118 return Q.promise(function(resolve, reject) {
119 self[rawCacheProperty].set(key, value, absoluteExpiration, function(err) {
120 if (err) {
121 return reject(err);
122 }
123 return resolve();
124 });
125 });
126
127};
128
129/**
130 * Removes a cached value.
131 * @abstract
132 * @param {string} key - A string that represents the key of the cached value to be removed
133 * @returns {Promise|*}
134 */
135DefaultCacheStrategy.prototype.remove = function(key) {
136 var self = this;
137 return Q.promise(function(resolve, reject) {
138 self[rawCacheProperty].set(key, function(err) {
139 if (err) {
140 return reject(err);
141 }
142 return resolve();
143 });
144 });
145};
146
147/**
148 * Flush all cached data.
149 * @abstract
150 * @returns {Promise|*}
151 */
152DefaultCacheStrategy.prototype.clear = function() {
153 this[rawCacheProperty].flushAll();
154 return Q();
155};
156
157/**
158 * Gets a cached value defined by the given key.
159 * @param {string} key
160 * @returns {Promise|*}
161 */
162DefaultCacheStrategy.prototype.get = function(key) {
163 return Q.nfbind(this[rawCacheProperty].get.bind(this[rawCacheProperty]))(key)
164 .then(function(res) {
165 return Q(res[key]);
166 });
167};
168
169/**
170 * Gets data from cache or executes the defined function and adds the result to the cache with the specified key
171 * @param {string|*} key - A string which represents the key of the cached data
172 * @param {Function} fn - A function to execute if data will not be found in cache
173 * @param {number=} absoluteExpiration - An absolute expiration time in seconds. This parameter is optional.
174 * @returns {Promise|*}
175 */
176DefaultCacheStrategy.prototype.getOrDefault = function(key, fn, absoluteExpiration) {
177 var self = this;
178 Args.check(_.isFunction(fn),'Invalid argument. Expected function.');
179 return self.get(key).then(function(res) {
180 if (_.isNil(res)) {
181 var source = fn();
182 Args.check(typeof source !== 'undefined' && typeof source.then === 'function', 'Invalid argument. Expected a valid promise.');
183 return source.then(function (res) {
184 if (_.isNil(res)) {
185 return Q();
186 }
187 return self.add(key, res, absoluteExpiration).then(function () {
188 return Q(res);
189 });
190 });
191 }
192 return Q(res);
193});
194};
195
196
197if (typeof exports !== 'undefined')
198{
199 module.exports.CacheStrategy = CacheStrategy;
200 module.exports.DefaultCacheStrategy = DefaultCacheStrategy;
201}
\No newline at end of file