UNPKG

12.2 kBJavaScriptView Raw
1"use strict";
2// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3// SPDX-License-Identifier: Apache-2.0
4Object.defineProperty(exports, "__esModule", { value: true });
5var tslib_1 = require("tslib");
6var Utils_1 = require("./Utils");
7var StorageCache_1 = require("./StorageCache");
8var core_1 = require("@aws-amplify/core");
9var logger = new core_1.ConsoleLogger('InMemoryCache');
10/**
11 * Customized in-memory cache with LRU implemented
12 * @member cacheObj - object which store items
13 * @member cacheList - list of keys in the cache with LRU
14 * @member curSizeInBytes - current size of the cache
15 * @member maxPriority - max of the priority
16 * @member cacheSizeLimit - the limit of cache size
17 */
18var InMemoryCacheClass = /** @class */ (function (_super) {
19 tslib_1.__extends(InMemoryCacheClass, _super);
20 /**
21 * initialize the cache
22 *
23 * @param config - the configuration of the cache
24 */
25 function InMemoryCacheClass(config) {
26 var _this = this;
27 var cacheConfig = config
28 ? Object.assign({}, Utils_1.defaultConfig, config)
29 : Utils_1.defaultConfig;
30 _this = _super.call(this, cacheConfig) || this;
31 logger.debug('now we start!');
32 _this.cacheList = [];
33 _this.curSizeInBytes = 0;
34 _this.maxPriority = 5;
35 _this.getItem = _this.getItem.bind(_this);
36 _this.setItem = _this.setItem.bind(_this);
37 _this.removeItem = _this.removeItem.bind(_this);
38 // initialize list for every priority
39 for (var i = 0; i < _this.maxPriority; i += 1) {
40 _this.cacheList[i] = new Utils_1.CacheList();
41 }
42 return _this;
43 }
44 /**
45 * decrease current size of the cache
46 *
47 * @param amount - the amount of the cache size which needs to be decreased
48 */
49 InMemoryCacheClass.prototype._decreaseCurSizeInBytes = function (amount) {
50 this.curSizeInBytes -= amount;
51 };
52 /**
53 * increase current size of the cache
54 *
55 * @param amount - the amount of the cache szie which need to be increased
56 */
57 InMemoryCacheClass.prototype._increaseCurSizeInBytes = function (amount) {
58 this.curSizeInBytes += amount;
59 };
60 /**
61 * check whether item is expired
62 *
63 * @param key - the key of the item
64 *
65 * @return true if the item is expired.
66 */
67 InMemoryCacheClass.prototype._isExpired = function (key) {
68 var text = Utils_1.CacheObject.getItem(key);
69 var item = JSON.parse(text);
70 if (Utils_1.getCurrTime() >= item.expires) {
71 return true;
72 }
73 return false;
74 };
75 /**
76 * delete item from cache
77 *
78 * @param prefixedKey - the key of the item
79 * @param listIdx - indicates which cache list the key belongs to
80 */
81 InMemoryCacheClass.prototype._removeItem = function (prefixedKey, listIdx) {
82 // delete the key from the list
83 this.cacheList[listIdx].removeItem(prefixedKey);
84 // decrease the current size of the cache
85 this._decreaseCurSizeInBytes(JSON.parse(Utils_1.CacheObject.getItem(prefixedKey)).byteSize);
86 // finally remove the item from memory
87 Utils_1.CacheObject.removeItem(prefixedKey);
88 };
89 /**
90 * put item into cache
91 *
92 * @param prefixedKey - the key of the item
93 * @param itemData - the value of the item
94 * @param itemSizeInBytes - the byte size of the item
95 * @param listIdx - indicates which cache list the key belongs to
96 */
97 InMemoryCacheClass.prototype._setItem = function (prefixedKey, item, listIdx) {
98 // insert the key into the list
99 this.cacheList[listIdx].insertItem(prefixedKey);
100 // increase the current size of the cache
101 this._increaseCurSizeInBytes(item.byteSize);
102 // finally add the item into memory
103 Utils_1.CacheObject.setItem(prefixedKey, JSON.stringify(item));
104 };
105 /**
106 * see whether cache is full
107 *
108 * @param itemSize
109 *
110 * @return true if cache is full
111 */
112 InMemoryCacheClass.prototype._isCacheFull = function (itemSize) {
113 return this.curSizeInBytes + itemSize > this.config.capacityInBytes;
114 };
115 /**
116 * check whether the cache contains the key
117 *
118 * @param key
119 */
120 InMemoryCacheClass.prototype.containsKey = function (key) {
121 var prefixedKey = this.config.keyPrefix + key;
122 for (var i = 0; i < this.maxPriority; i += 1) {
123 if (this.cacheList[i].containsKey(prefixedKey)) {
124 return i + 1;
125 }
126 }
127 return -1;
128 };
129 /**
130 * * Set item into cache. You can put number, string, boolean or object.
131 * The cache will first check whether has the same key.
132 * If it has, it will delete the old item and then put the new item in
133 * The cache will pop out items if it is full
134 * You can specify the cache item options. The cache will abort and output a warning:
135 * If the key is invalid
136 * If the size of the item exceeds itemMaxSize.
137 * If the value is undefined
138 * If incorrect cache item configuration
139 * If error happened with browser storage
140 *
141 * @param key - the key of the item
142 * @param value - the value of the item
143 * @param options - optional, the specified meta-data
144 *
145 * @throws if the item is too big which exceeds the limit of single item size
146 * @throws if the key is invalid
147 */
148 InMemoryCacheClass.prototype.setItem = function (key, value, options) {
149 var prefixedKey = this.config.keyPrefix + key;
150 // invalid keys
151 if (prefixedKey === this.config.keyPrefix ||
152 prefixedKey === this.cacheCurSizeKey) {
153 logger.warn("Invalid key: should not be empty or 'CurSize'");
154 return;
155 }
156 if (typeof value === 'undefined') {
157 logger.warn("The value of item should not be undefined!");
158 return;
159 }
160 var cacheItemOptions = {
161 priority: options && options.priority !== undefined
162 ? options.priority
163 : this.config.defaultPriority,
164 expires: options && options.expires !== undefined
165 ? options.expires
166 : this.config.defaultTTL + Utils_1.getCurrTime(),
167 };
168 if (cacheItemOptions.priority < 1 || cacheItemOptions.priority > 5) {
169 logger.warn("Invalid parameter: priority due to out or range. It should be within 1 and 5.");
170 return;
171 }
172 var item = this.fillCacheItem(prefixedKey, value, cacheItemOptions);
173 // check wether this item is too big;
174 if (item.byteSize > this.config.itemMaxSize) {
175 logger.warn("Item with key: " + key + " you are trying to put into is too big!");
176 return;
177 }
178 // if key already in the cache, then delete it.
179 var presentKeyPrio = this.containsKey(key);
180 if (presentKeyPrio !== -1) {
181 this._removeItem(prefixedKey, presentKeyPrio - 1);
182 }
183 // pop out items in the cache when cache is full based on LRU
184 // first start from lowest priority cache list
185 var cacheListIdx = this.maxPriority - 1;
186 while (this._isCacheFull(item.byteSize) && cacheListIdx >= 0) {
187 if (!this.cacheList[cacheListIdx].isEmpty()) {
188 var popedItemKey = this.cacheList[cacheListIdx].getLastItem();
189 this._removeItem(popedItemKey, cacheListIdx);
190 }
191 else {
192 cacheListIdx -= 1;
193 }
194 }
195 this._setItem(prefixedKey, item, Number(item.priority) - 1);
196 };
197 /**
198 * Get item from cache. It will return null if item doesn’t exist or it has been expired.
199 * If you specified callback function in the options,
200 * then the function will be executed if no such item in the cache
201 * and finally put the return value into cache.
202 * Please make sure the callback function will return the value you want to put into the cache.
203 * The cache will abort output a warning:
204 * If the key is invalid
205 *
206 * @param key - the key of the item
207 * @param options - the options of callback function
208 */
209 InMemoryCacheClass.prototype.getItem = function (key, options) {
210 var ret = null;
211 var prefixedKey = this.config.keyPrefix + key;
212 if (prefixedKey === this.config.keyPrefix ||
213 prefixedKey === this.cacheCurSizeKey) {
214 logger.warn("Invalid key: should not be empty or 'CurSize'");
215 return null;
216 }
217 // check whether it's in the cachelist
218 var presentKeyPrio = this.containsKey(key);
219 if (presentKeyPrio !== -1) {
220 if (this._isExpired(prefixedKey)) {
221 // if expired, remove that item and return null
222 this._removeItem(prefixedKey, presentKeyPrio - 1);
223 }
224 else {
225 // if not expired, great, return the value and refresh it
226 ret = Utils_1.CacheObject.getItem(prefixedKey);
227 var item = JSON.parse(ret);
228 this.cacheList[item.priority - 1].refresh(prefixedKey);
229 return item.data;
230 }
231 }
232 if (options && options.callback !== undefined) {
233 var val = options.callback();
234 if (val !== null) {
235 this.setItem(key, val, options);
236 }
237 return val;
238 }
239 return null;
240 };
241 /**
242 * remove item from the cache
243 *
244 * @param key - the key of the item
245 */
246 InMemoryCacheClass.prototype.removeItem = function (key) {
247 var prefixedKey = this.config.keyPrefix + key;
248 // check if the key is in the cache
249 var presentKeyPrio = this.containsKey(key);
250 if (presentKeyPrio !== -1) {
251 this._removeItem(prefixedKey, presentKeyPrio - 1);
252 }
253 };
254 /**
255 * clear the entire cache
256 */
257 InMemoryCacheClass.prototype.clear = function () {
258 var e_1, _a;
259 for (var i = 0; i < this.maxPriority; i += 1) {
260 try {
261 for (var _b = (e_1 = void 0, tslib_1.__values(this.cacheList[i].getKeys())), _c = _b.next(); !_c.done; _c = _b.next()) {
262 var key = _c.value;
263 this._removeItem(key, i);
264 }
265 }
266 catch (e_1_1) { e_1 = { error: e_1_1 }; }
267 finally {
268 try {
269 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
270 }
271 finally { if (e_1) throw e_1.error; }
272 }
273 }
274 };
275 /**
276 * Return all the keys in the cache.
277 */
278 InMemoryCacheClass.prototype.getAllKeys = function () {
279 var e_2, _a;
280 var keys = [];
281 for (var i = 0; i < this.maxPriority; i += 1) {
282 try {
283 for (var _b = (e_2 = void 0, tslib_1.__values(this.cacheList[i].getKeys())), _c = _b.next(); !_c.done; _c = _b.next()) {
284 var key = _c.value;
285 keys.push(key.substring(this.config.keyPrefix.length));
286 }
287 }
288 catch (e_2_1) { e_2 = { error: e_2_1 }; }
289 finally {
290 try {
291 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
292 }
293 finally { if (e_2) throw e_2.error; }
294 }
295 }
296 return keys;
297 };
298 /**
299 * return the current size of the cache
300 *
301 * @return the current size of the cache
302 */
303 InMemoryCacheClass.prototype.getCacheCurSize = function () {
304 return this.curSizeInBytes;
305 };
306 /**
307 * Return a new instance of cache with customized configuration.
308 * @param config - the customized configuration
309 */
310 InMemoryCacheClass.prototype.createInstance = function (config) {
311 return new InMemoryCacheClass(config);
312 };
313 return InMemoryCacheClass;
314}(StorageCache_1.StorageCache));
315exports.InMemoryCacheClass = InMemoryCacheClass;
316exports.InMemoryCache = new InMemoryCacheClass();
317//# sourceMappingURL=InMemoryCache.js.map
\No newline at end of file