UNPKG

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