1 | "use strict";
|
---|
2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
---|
3 | return new (P || (P = Promise))(function (resolve, reject) {
|
---|
4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
---|
5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
---|
6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
---|
7 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
---|
8 | });
|
---|
9 | };
|
---|
10 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
---|
11 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
---|
12 | };
|
---|
13 | Object.defineProperty(exports, "__esModule", { value: true });
|
---|
14 | const p_defer_1 = __importDefault(require("p-defer"));
|
---|
15 | function mapAgeCleaner(map, property = 'maxAge') {
|
---|
16 | let processingKey;
|
---|
17 | let processingTimer;
|
---|
18 | let processingDeferred;
|
---|
19 | const cleanup = () => __awaiter(this, void 0, void 0, function* () {
|
---|
20 | if (processingKey !== undefined) {
|
---|
21 | // If we are already processing an item, we can safely exit
|
---|
22 | return;
|
---|
23 | }
|
---|
24 | const setupTimer = (item) => __awaiter(this, void 0, void 0, function* () {
|
---|
25 | processingDeferred = p_defer_1.default();
|
---|
26 | const delay = item[1][property] - Date.now();
|
---|
27 | if (delay <= 0) {
|
---|
28 | // Remove the item immediately if the delay is equal to or below 0
|
---|
29 | map.delete(item[0]);
|
---|
30 | processingDeferred.resolve();
|
---|
31 | return;
|
---|
32 | }
|
---|
33 | // Keep track of the current processed key
|
---|
34 | processingKey = item[0];
|
---|
35 | processingTimer = setTimeout(() => {
|
---|
36 | // Remove the item when the timeout fires
|
---|
37 | map.delete(item[0]);
|
---|
38 | if (processingDeferred) {
|
---|
39 | processingDeferred.resolve();
|
---|
40 | }
|
---|
41 | }, delay);
|
---|
42 | // tslint:disable-next-line:strict-type-predicates
|
---|
43 | if (typeof processingTimer.unref === 'function') {
|
---|
44 | // Don't hold up the process from exiting
|
---|
45 | processingTimer.unref();
|
---|
46 | }
|
---|
47 | return processingDeferred.promise;
|
---|
48 | });
|
---|
49 | try {
|
---|
50 | for (const entry of map) {
|
---|
51 | yield setupTimer(entry);
|
---|
52 | }
|
---|
53 | }
|
---|
54 | catch (_a) {
|
---|
55 | // Do nothing if an error occurs, this means the timer was cleaned up and we should stop processing
|
---|
56 | }
|
---|
57 | processingKey = undefined;
|
---|
58 | });
|
---|
59 | const reset = () => {
|
---|
60 | processingKey = undefined;
|
---|
61 | if (processingTimer !== undefined) {
|
---|
62 | clearTimeout(processingTimer);
|
---|
63 | processingTimer = undefined;
|
---|
64 | }
|
---|
65 | if (processingDeferred !== undefined) { // tslint:disable-line:early-exit
|
---|
66 | processingDeferred.reject(undefined);
|
---|
67 | processingDeferred = undefined;
|
---|
68 | }
|
---|
69 | };
|
---|
70 | const originalSet = map.set.bind(map);
|
---|
71 | map.set = (key, value) => {
|
---|
72 | if (map.has(key)) {
|
---|
73 | // If the key already exist, remove it so we can add it back at the end of the map.
|
---|
74 | map.delete(key);
|
---|
75 | }
|
---|
76 | // Call the original `map.set`
|
---|
77 | const result = originalSet(key, value);
|
---|
78 | // If we are already processing a key and the key added is the current processed key, stop processing it
|
---|
79 | if (processingKey && processingKey === key) {
|
---|
80 | reset();
|
---|
81 | }
|
---|
82 | // Always run the cleanup method in case it wasn't started yet
|
---|
83 | cleanup(); // tslint:disable-line:no-floating-promises
|
---|
84 | return result;
|
---|
85 | };
|
---|
86 | cleanup(); // tslint:disable-line:no-floating-promises
|
---|
87 | return map;
|
---|
88 | }
|
---|
89 | exports.default = mapAgeCleaner;
|
---|
90 | // Add support for CJS
|
---|
91 | module.exports = mapAgeCleaner;
|
---|
92 | module.exports.default = mapAgeCleaner;
|
---|