pstream is dead; long live pstream
taciturnaxolotl.github.io/pstream-ng/
1export class SimpleCache<Key, Value> {
2 protected readonly INTERVAL_MS = 2 * 60 * 1000; // 2 minutes
3
4 protected _interval: ReturnType<typeof setTimeout> | null = null;
5
6 protected _compare: ((a: Key, b: Key) => boolean) | null = null;
7
8 protected _storage: { key: Key; value: Value; expiry: Date }[] = [];
9
10 private static isExpired(entry: { expiry: Date }): boolean {
11 return entry.expiry.getTime() <= Date.now();
12 }
13
14 private pruneExpired(): void {
15 this._storage = this._storage.filter(
16 (entry) => !SimpleCache.isExpired(entry),
17 );
18 }
19
20 /*
21 ** initialize store, will start the interval
22 */
23 public initialize(): void {
24 if (this._interval) throw new Error("cache is already initialized");
25 this._interval = setInterval(() => {
26 this.pruneExpired();
27 }, this.INTERVAL_MS);
28 }
29
30 /*
31 ** destroy cache instance, its not safe to use the instance after calling this
32 */
33 public destroy(): void {
34 if (this._interval) clearInterval(this._interval);
35 this._interval = null;
36 this.clear();
37 }
38
39 /*
40 ** Set compare function, function must return true if A & B are equal
41 */
42 public setCompare(compare: (a: Key, b: Key) => boolean): void {
43 this._compare = compare;
44 }
45
46 /*
47 ** check if cache contains the item
48 */
49 public has(key: Key): boolean {
50 return !!this.get(key);
51 }
52
53 /*
54 ** get item from cache
55 */
56 public get(key: Key): Value | undefined {
57 if (!this._compare) throw new Error("Compare function not set");
58 this.pruneExpired();
59 const foundValue = this._storage.find(
60 (item) => this._compare && this._compare(item.key, key),
61 );
62 if (!foundValue) return undefined;
63 if (SimpleCache.isExpired(foundValue)) {
64 this.remove(key);
65 return undefined;
66 }
67 return foundValue.value;
68 }
69
70 /*
71 ** set item from cache, if it already exists, it will overwrite
72 */
73 public set(key: Key, value: Value, expirySeconds: number): void {
74 if (!this._compare) throw new Error("Compare function not set");
75 this.pruneExpired();
76 const foundValue = this._storage.find(
77 (item) => this._compare && this._compare(item.key, key),
78 );
79 const expiry = new Date(new Date().getTime() + expirySeconds * 1000);
80
81 // overwrite old value
82 if (foundValue) {
83 foundValue.key = key;
84 foundValue.value = value;
85 foundValue.expiry = expiry;
86 return;
87 }
88
89 // add new value to storage
90 this._storage.push({
91 key,
92 value,
93 expiry,
94 });
95 }
96
97 /*
98 ** remove item from cache
99 */
100 public remove(key: Key): void {
101 if (!this._compare) throw new Error("Compare function not set");
102 this._storage = this._storage.filter(
103 (val) => !(this._compare && this._compare(val.key, key)),
104 );
105 }
106
107 /*
108 ** clear entire cache storage
109 */
110 public clear(): void {
111 this._storage = [];
112 }
113}