jopi-toolkit 3.1.25 → 3.1.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/jk_fs/jBundler_ifServer.d.ts +1 -1
- package/dist/jk_logs/index.js +2 -2
- package/dist/jk_logs/index.js.map +1 -1
- package/dist/jk_memcache/_logs.d.ts +1 -0
- package/dist/jk_memcache/_logs.js +3 -0
- package/dist/jk_memcache/_logs.js.map +1 -0
- package/dist/jk_memcache/index.d.ts +127 -0
- package/dist/jk_memcache/index.js +415 -0
- package/dist/jk_memcache/index.js.map +1 -0
- package/dist/jk_tools/common.d.ts +6 -0
- package/dist/jk_tools/common.js +6 -0
- package/dist/jk_tools/common.js.map +1 -1
- package/package.json +8 -4
- package/src/jk_logs/index.ts +2 -2
- package/src/jk_memcache/README.md +66 -0
- package/src/jk_memcache/_logs.ts +3 -0
- package/src/jk_memcache/index.ts +498 -0
- package/src/jk_tools/common.ts +6 -0
|
@@ -77,7 +77,7 @@ export declare const join: typeof path.join;
|
|
|
77
77
|
export declare const resolve: typeof path.resolve;
|
|
78
78
|
export declare const dirname: typeof path.dirname;
|
|
79
79
|
export declare const extname: typeof path.extname;
|
|
80
|
-
export declare const sep: "
|
|
80
|
+
export declare const sep: "/" | "\\";
|
|
81
81
|
export declare const isAbsolute: typeof path.isAbsolute;
|
|
82
82
|
export declare const normalize: typeof path.normalize;
|
|
83
83
|
export declare const basename: typeof path.basename;
|
package/dist/jk_logs/index.js
CHANGED
|
@@ -26,7 +26,7 @@ export const formater_simpleJson = (entry) => {
|
|
|
26
26
|
export const formater_dateTypeTitleSourceData = (entry) => {
|
|
27
27
|
const date = formatDate1(entry.date);
|
|
28
28
|
let json = entry.data ? JSON.stringify(entry.data) : "";
|
|
29
|
-
const title = (entry.title || "").padEnd(50, " ");
|
|
29
|
+
const title = String(entry.title || "").padEnd(50, " ");
|
|
30
30
|
json = entry.logger + " |>" + json;
|
|
31
31
|
switch (entry.level) {
|
|
32
32
|
case LogLevel.ERROR:
|
|
@@ -43,7 +43,7 @@ export const formater_dateTypeTitleSourceData = (entry) => {
|
|
|
43
43
|
};
|
|
44
44
|
export const formater_typeTitleSourceData_colored = (entry) => {
|
|
45
45
|
let json = entry.data ? JSON.stringify(entry.data) : "";
|
|
46
|
-
const title = (entry.title || "").padEnd(50, " ");
|
|
46
|
+
const title = String(entry.title || "").padEnd(50, " ");
|
|
47
47
|
json = entry.timeDif === undefined
|
|
48
48
|
? `${entry.logger} ${json}` : `${entry.logger} (${entry.timeDif} ms) ${json}`;
|
|
49
49
|
switch (entry.level) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jk_logs/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAErC,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAC,IAAI,EAAC,MAAM,wBAAwB,CAAC;AAiB5C,MAAM,CAAN,IAAY,QAMX;AAND,WAAY,QAAQ;IAChB,uCAAQ,CAAA;IACR,uCAAQ,CAAA;IACR,uCAAQ,CAAA;IACR,yCAAS,CAAA;IACT,wCAAS,CAAA;AACb,CAAC,EANW,QAAQ,KAAR,QAAQ,QAMnB;AAID,WAAW;AAEX,iBAAiB;AAEjB,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC;AAC3B,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC;AACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC;AAC7B,MAAM,UAAU,GAAG,QAAQ,CAAC,YAAY,CAAC;AACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC;AAE/B,MAAM,UAAU,WAAW,CAAC,SAAiB;IACzC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;IACjC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAqB,CAAC,KAAe,EAAE,EAAE;IACrE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gCAAgC,GAAqB,CAAC,KAAe,EAAE,EAAE;IAClF,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAErC,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jk_logs/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const logMemCache: import("jopi-toolkit/jk_logs").Logger;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_logs.js","sourceRoot":"","sources":["../../src/jk_memcache/_logs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAC;AAE/C,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
export interface CacheEntryOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Importance level. Higher value means less likely to be evicted by GC.
|
|
4
|
+
* Default: 1
|
|
5
|
+
*/
|
|
6
|
+
importance?: number;
|
|
7
|
+
/**
|
|
8
|
+
* Time to live in milliseconds.
|
|
9
|
+
*/
|
|
10
|
+
ttl?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Absolute expiration date.
|
|
13
|
+
*/
|
|
14
|
+
expiresAt?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Arbitrary metadata (optional).
|
|
17
|
+
*/
|
|
18
|
+
meta?: any;
|
|
19
|
+
}
|
|
20
|
+
export interface JkMemCacheOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Name of the cache instance (used for logs).
|
|
23
|
+
*/
|
|
24
|
+
name: string;
|
|
25
|
+
/**
|
|
26
|
+
* Maximum number of items in cache.
|
|
27
|
+
* Default: Infinity
|
|
28
|
+
*/
|
|
29
|
+
maxCount?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Maximum size in bytes.
|
|
32
|
+
* Default: 50MB (50 * 1024 * 1024)
|
|
33
|
+
*/
|
|
34
|
+
maxSize?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Interval in milliseconds for the recurrent GC.
|
|
37
|
+
* Default: 60000 (1 minute)
|
|
38
|
+
*/
|
|
39
|
+
cleanupInterval?: number;
|
|
40
|
+
}
|
|
41
|
+
export declare class JkMemCache {
|
|
42
|
+
private _storage;
|
|
43
|
+
private _currentSize;
|
|
44
|
+
private _options;
|
|
45
|
+
private _intervalId;
|
|
46
|
+
private _name;
|
|
47
|
+
constructor(options: JkMemCacheOptions);
|
|
48
|
+
/**
|
|
49
|
+
* Start the automatic cleanup interval.
|
|
50
|
+
*/
|
|
51
|
+
startAutoCleanup(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Stop the automatic cleanup interval.
|
|
54
|
+
*/
|
|
55
|
+
stopAutoCleanup(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Add or update an item in the cache.
|
|
58
|
+
*/
|
|
59
|
+
set(key: string, value: string | ArrayBuffer | Uint8Array | object, options?: CacheEntryOptions): void;
|
|
60
|
+
/**
|
|
61
|
+
* Retrieve an item from the cache.
|
|
62
|
+
*/
|
|
63
|
+
get<T = any>(key: string, peek?: boolean): T | null;
|
|
64
|
+
/**
|
|
65
|
+
* Retrieve an item from the cache with its metadata.
|
|
66
|
+
*/
|
|
67
|
+
getWithMeta<T = any>(key: string, peek?: boolean): {
|
|
68
|
+
value: T;
|
|
69
|
+
meta: any;
|
|
70
|
+
} | null;
|
|
71
|
+
/**
|
|
72
|
+
* Check if an item exists in the cache and is not expired.
|
|
73
|
+
* Does not increment accessCount.
|
|
74
|
+
*/
|
|
75
|
+
has(key: string): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Manually delete an item.
|
|
78
|
+
*/
|
|
79
|
+
delete(key: string): void;
|
|
80
|
+
/**
|
|
81
|
+
* Clear all items.
|
|
82
|
+
*/
|
|
83
|
+
clear(): void;
|
|
84
|
+
/**
|
|
85
|
+
* Get current cache stats.
|
|
86
|
+
*/
|
|
87
|
+
getStats(): {
|
|
88
|
+
count: number;
|
|
89
|
+
size: number;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Iterate over all valid keys.
|
|
93
|
+
*/
|
|
94
|
+
keys(): Generator<string>;
|
|
95
|
+
/**
|
|
96
|
+
* Iterate over keys starting with a prefix.
|
|
97
|
+
*/
|
|
98
|
+
keysStartingWith(prefix: string): Generator<string>;
|
|
99
|
+
/**
|
|
100
|
+
* Iterate over keys ending with a suffix.
|
|
101
|
+
*/
|
|
102
|
+
keysEndingWith(suffix: string): Generator<string>;
|
|
103
|
+
/**
|
|
104
|
+
* Iterate over keys containing a specific text.
|
|
105
|
+
*/
|
|
106
|
+
keysContaining(text: string): Generator<string>;
|
|
107
|
+
/**
|
|
108
|
+
* Check if we need to evict entries to fit a new one (or if limits are exceeded).
|
|
109
|
+
*/
|
|
110
|
+
private needsEviction;
|
|
111
|
+
/**
|
|
112
|
+
* Perform recurrent cleanup (expiration only).
|
|
113
|
+
*/
|
|
114
|
+
private performCleanup;
|
|
115
|
+
/**
|
|
116
|
+
* Evict items to make space/reduce count.
|
|
117
|
+
* Strategy: Calculate a score. Lower score = evicted first.
|
|
118
|
+
* Factors:
|
|
119
|
+
* - expired (immediate kill)
|
|
120
|
+
* - importance (higher = keep)
|
|
121
|
+
* - accessCount (higher = keep)
|
|
122
|
+
*
|
|
123
|
+
* Score = (importance * 1000) + (accessCount)
|
|
124
|
+
* (Simplified logic)
|
|
125
|
+
*/
|
|
126
|
+
private evictFor;
|
|
127
|
+
}
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { logMemCache } from "./_logs.js";
|
|
2
|
+
export class JkMemCache {
|
|
3
|
+
_storage = new Map();
|
|
4
|
+
_currentSize = 0;
|
|
5
|
+
_options;
|
|
6
|
+
_intervalId = null;
|
|
7
|
+
_name;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this._options = {
|
|
10
|
+
name: options.name,
|
|
11
|
+
maxCount: options.maxCount ?? Infinity,
|
|
12
|
+
maxSize: options.maxSize ?? 50 * 1024 * 1024,
|
|
13
|
+
cleanupInterval: options.cleanupInterval ?? 60000,
|
|
14
|
+
};
|
|
15
|
+
this._name = options.name;
|
|
16
|
+
logMemCache.info(`Cache [${this._name}] initialized`);
|
|
17
|
+
if (this._options.cleanupInterval > 0) {
|
|
18
|
+
this.startAutoCleanup();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Start the automatic cleanup interval.
|
|
23
|
+
*/
|
|
24
|
+
startAutoCleanup() {
|
|
25
|
+
if (this._intervalId)
|
|
26
|
+
clearInterval(this._intervalId);
|
|
27
|
+
this._intervalId = setInterval(() => {
|
|
28
|
+
this.performCleanup();
|
|
29
|
+
}, this._options.cleanupInterval);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Stop the automatic cleanup interval.
|
|
33
|
+
*/
|
|
34
|
+
stopAutoCleanup() {
|
|
35
|
+
if (this._intervalId) {
|
|
36
|
+
clearInterval(this._intervalId);
|
|
37
|
+
this._intervalId = null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Add or update an item in the cache.
|
|
42
|
+
*/
|
|
43
|
+
set(key, value, options = {}) {
|
|
44
|
+
// 1. Prepare new entry details
|
|
45
|
+
let storedValue;
|
|
46
|
+
let type;
|
|
47
|
+
let size = 0;
|
|
48
|
+
// Meta size calculation
|
|
49
|
+
const metaSize = options.meta ? JSON.stringify(options.meta).length * 2 : 0;
|
|
50
|
+
if (value instanceof ArrayBuffer) {
|
|
51
|
+
storedValue = value;
|
|
52
|
+
type = 'buffer';
|
|
53
|
+
size = value.byteLength;
|
|
54
|
+
}
|
|
55
|
+
else if (value instanceof Uint8Array) {
|
|
56
|
+
storedValue = value;
|
|
57
|
+
type = 'buffer';
|
|
58
|
+
size = value.byteLength;
|
|
59
|
+
}
|
|
60
|
+
else if (typeof value === 'string') {
|
|
61
|
+
storedValue = value;
|
|
62
|
+
type = 'string';
|
|
63
|
+
size = value.length * 2; // Approximation for JS string memory
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
storedValue = JSON.stringify(value);
|
|
67
|
+
type = 'json';
|
|
68
|
+
size = storedValue.length * 2;
|
|
69
|
+
}
|
|
70
|
+
// Overhead for object structure (approximate) + Meta size
|
|
71
|
+
size += 100 + metaSize;
|
|
72
|
+
// 2. Check overlap
|
|
73
|
+
if (this._storage.has(key)) {
|
|
74
|
+
this.delete(key);
|
|
75
|
+
}
|
|
76
|
+
// 3. Calculate Expiration
|
|
77
|
+
let expiresAt = null;
|
|
78
|
+
if (options.expiresAt) {
|
|
79
|
+
expiresAt = options.expiresAt;
|
|
80
|
+
}
|
|
81
|
+
else if (options.ttl) {
|
|
82
|
+
expiresAt = Date.now() + options.ttl;
|
|
83
|
+
}
|
|
84
|
+
const entry = {
|
|
85
|
+
key,
|
|
86
|
+
value: storedValue,
|
|
87
|
+
type,
|
|
88
|
+
size,
|
|
89
|
+
createdAt: Date.now(),
|
|
90
|
+
expiresAt,
|
|
91
|
+
accessCount: 0,
|
|
92
|
+
importance: options.importance ?? 1,
|
|
93
|
+
meta: options.meta,
|
|
94
|
+
};
|
|
95
|
+
// 4. Check if item is too big for the cache entirely
|
|
96
|
+
if (entry.size > this._options.maxSize) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// 5. Check if we need to make space
|
|
100
|
+
if (this.needsEviction(entry.size)) {
|
|
101
|
+
this.evictFor(entry.size);
|
|
102
|
+
if (this.needsEviction(entry.size)) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
this._storage.set(key, entry);
|
|
107
|
+
this._currentSize += size;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Retrieve an item from the cache.
|
|
111
|
+
*/
|
|
112
|
+
get(key, peek = false) {
|
|
113
|
+
const entry = this._storage.get(key);
|
|
114
|
+
if (!entry)
|
|
115
|
+
return null;
|
|
116
|
+
if (entry.expiresAt && entry.expiresAt < Date.now()) {
|
|
117
|
+
this.delete(key);
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
if (!peek)
|
|
121
|
+
entry.accessCount++;
|
|
122
|
+
if (entry.type === 'buffer') {
|
|
123
|
+
return entry.value;
|
|
124
|
+
}
|
|
125
|
+
else if (entry.type === 'json') {
|
|
126
|
+
return JSON.parse(entry.value);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
return entry.value;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Retrieve an item from the cache with its metadata.
|
|
134
|
+
*/
|
|
135
|
+
getWithMeta(key, peek = false) {
|
|
136
|
+
const entry = this._storage.get(key);
|
|
137
|
+
if (!entry)
|
|
138
|
+
return null;
|
|
139
|
+
if (entry.expiresAt && entry.expiresAt < Date.now()) {
|
|
140
|
+
this.delete(key);
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
if (!peek)
|
|
144
|
+
entry.accessCount++;
|
|
145
|
+
let value;
|
|
146
|
+
if (entry.type === 'buffer') {
|
|
147
|
+
value = entry.value;
|
|
148
|
+
}
|
|
149
|
+
else if (entry.type === 'json') {
|
|
150
|
+
value = JSON.parse(entry.value);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
value = entry.value;
|
|
154
|
+
}
|
|
155
|
+
return { value, meta: entry.meta };
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Check if an item exists in the cache and is not expired.
|
|
159
|
+
* Does not increment accessCount.
|
|
160
|
+
*/
|
|
161
|
+
has(key) {
|
|
162
|
+
const entry = this._storage.get(key);
|
|
163
|
+
if (!entry)
|
|
164
|
+
return false;
|
|
165
|
+
if (entry.expiresAt && entry.expiresAt < Date.now()) {
|
|
166
|
+
this.delete(key);
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Manually delete an item.
|
|
173
|
+
*/
|
|
174
|
+
delete(key) {
|
|
175
|
+
const entry = this._storage.get(key);
|
|
176
|
+
if (entry) {
|
|
177
|
+
this._currentSize -= entry.size;
|
|
178
|
+
this._storage.delete(key);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Clear all items.
|
|
183
|
+
*/
|
|
184
|
+
clear() {
|
|
185
|
+
this._storage.clear();
|
|
186
|
+
this._currentSize = 0;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Get current cache stats.
|
|
190
|
+
*/
|
|
191
|
+
getStats() {
|
|
192
|
+
return {
|
|
193
|
+
count: this._storage.size,
|
|
194
|
+
size: this._currentSize,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Iterate over all valid keys.
|
|
199
|
+
*/
|
|
200
|
+
*keys() {
|
|
201
|
+
const now = Date.now();
|
|
202
|
+
for (const [key, entry] of this._storage) {
|
|
203
|
+
if (entry.expiresAt && now > entry.expiresAt) {
|
|
204
|
+
this.delete(key);
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
yield key;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Iterate over keys starting with a prefix.
|
|
212
|
+
*/
|
|
213
|
+
*keysStartingWith(prefix) {
|
|
214
|
+
for (const key of this.keys()) {
|
|
215
|
+
if (key.startsWith(prefix))
|
|
216
|
+
yield key;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Iterate over keys ending with a suffix.
|
|
221
|
+
*/
|
|
222
|
+
*keysEndingWith(suffix) {
|
|
223
|
+
for (const key of this.keys()) {
|
|
224
|
+
if (key.endsWith(suffix))
|
|
225
|
+
yield key;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Iterate over keys containing a specific text.
|
|
230
|
+
*/
|
|
231
|
+
*keysContaining(text) {
|
|
232
|
+
for (const key of this.keys()) {
|
|
233
|
+
if (key.includes(text))
|
|
234
|
+
yield key;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Check if we need to evict entries to fit a new one (or if limits are exceeded).
|
|
239
|
+
*/
|
|
240
|
+
needsEviction(incomingSize) {
|
|
241
|
+
return ((this._storage.size + 1 > this._options.maxCount) ||
|
|
242
|
+
(this._currentSize + incomingSize > this._options.maxSize));
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Perform recurrent cleanup (expiration only).
|
|
246
|
+
*/
|
|
247
|
+
performCleanup() {
|
|
248
|
+
const now = Date.now();
|
|
249
|
+
let removedCount = 0;
|
|
250
|
+
logMemCache.info(`Cache [${this._name}] Recurrent GC started - ${JSON.stringify({
|
|
251
|
+
count: this._storage.size,
|
|
252
|
+
sizeMB: (this._currentSize / 1024 / 1024).toFixed(2)
|
|
253
|
+
})}`);
|
|
254
|
+
for (const [key, entry] of this._storage) {
|
|
255
|
+
if (entry.expiresAt && now > entry.expiresAt) {
|
|
256
|
+
this.delete(key);
|
|
257
|
+
removedCount++;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (removedCount > 0) {
|
|
261
|
+
logMemCache.info(`Cache [${this._name}] Recurrent GC finished - ${JSON.stringify({
|
|
262
|
+
removed: removedCount,
|
|
263
|
+
remaining: this._storage.size,
|
|
264
|
+
sizeMB: (this._currentSize / 1024 / 1024).toFixed(2)
|
|
265
|
+
})}`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Evict items to make space/reduce count.
|
|
270
|
+
* Strategy: Calculate a score. Lower score = evicted first.
|
|
271
|
+
* Factors:
|
|
272
|
+
* - expired (immediate kill)
|
|
273
|
+
* - importance (higher = keep)
|
|
274
|
+
* - accessCount (higher = keep)
|
|
275
|
+
*
|
|
276
|
+
* Score = (importance * 1000) + (accessCount)
|
|
277
|
+
* (Simplified logic)
|
|
278
|
+
*/
|
|
279
|
+
evictFor(requiredSpace) {
|
|
280
|
+
const now = Date.now();
|
|
281
|
+
logMemCache.info(`Cache [${this._name}] GC Eviction started (Memory Pressure) - ${JSON.stringify({
|
|
282
|
+
requiredSpace,
|
|
283
|
+
count: this._storage.size,
|
|
284
|
+
sizeMB: (this._currentSize / 1024 / 1024).toFixed(2)
|
|
285
|
+
})}`);
|
|
286
|
+
// 1. Remove expired first (In-place, no allocation)
|
|
287
|
+
for (const [key, entry] of this._storage) {
|
|
288
|
+
if (entry.expiresAt && now > entry.expiresAt) {
|
|
289
|
+
this.delete(key);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
// Optimization: Low Water Mark.
|
|
293
|
+
// To avoid frequent GC, when we evict, we try to go down to 90% capacity,
|
|
294
|
+
// creating a temporary buffer.
|
|
295
|
+
//
|
|
296
|
+
const safeSize = this._options.maxSize * 0.9;
|
|
297
|
+
const safeCount = this._options.maxCount * 0.9;
|
|
298
|
+
// Helper: Have we reached our goal?
|
|
299
|
+
// If strict is true, we aim for the buffer (90%).
|
|
300
|
+
// If strict is false, we just aim to fit the item (100%).
|
|
301
|
+
const isTargetReached = (strict) => {
|
|
302
|
+
// 1. Absolute requirement: Must fit the new item within MAX limits.
|
|
303
|
+
// needsEviction returns TRUE if we are OVER limits.
|
|
304
|
+
if (this.needsEviction(requiredSpace)) {
|
|
305
|
+
return false; // We are over max, so target is definitely NOT reached.
|
|
306
|
+
}
|
|
307
|
+
// 2. Buffer requirement: specific to strict mode
|
|
308
|
+
if (strict) {
|
|
309
|
+
// We are under MAX, but are we under SAFE limits?
|
|
310
|
+
return (this._currentSize + requiredSpace <= safeSize) && (this._storage.size <= safeCount);
|
|
311
|
+
}
|
|
312
|
+
// If not strict, and needsEviction was false, we are good.
|
|
313
|
+
return true;
|
|
314
|
+
};
|
|
315
|
+
// Helper to format log message
|
|
316
|
+
const logGC = (step, extra = {}) => {
|
|
317
|
+
logMemCache.info(`Cache [${this._name}] [GC] ${step} - ${JSON.stringify({
|
|
318
|
+
...extra,
|
|
319
|
+
count: this._storage.size,
|
|
320
|
+
sizeMB: (this._currentSize / 1024 / 1024).toFixed(2)
|
|
321
|
+
})}`);
|
|
322
|
+
};
|
|
323
|
+
if (isTargetReached(true)) {
|
|
324
|
+
logGC("Step 1 (Expired) sufficient");
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
// 2. Multi-step Eviction by Importance
|
|
328
|
+
const MAX_SEARCH_LEVEL = 10;
|
|
329
|
+
// We treat levels 1-5 as "recyclable" to build buffer.
|
|
330
|
+
// Levels 6-10 are "protected" -> only evicted if absolutely necessary to fit the item.
|
|
331
|
+
const BUFFER_TARGET_LEVEL = 5;
|
|
332
|
+
for (let level = 1; level <= MAX_SEARCH_LEVEL; level++) {
|
|
333
|
+
const candidates = [];
|
|
334
|
+
for (const entry of this._storage.values()) {
|
|
335
|
+
if (entry.importance === level) {
|
|
336
|
+
candidates.push(entry);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (candidates.length === 0)
|
|
340
|
+
continue;
|
|
341
|
+
candidates.sort((a, b) => {
|
|
342
|
+
if (a.accessCount !== b.accessCount) {
|
|
343
|
+
return a.accessCount - b.accessCount;
|
|
344
|
+
}
|
|
345
|
+
return a.createdAt - b.createdAt;
|
|
346
|
+
});
|
|
347
|
+
const aimForBuffer = level <= BUFFER_TARGET_LEVEL;
|
|
348
|
+
for (const candidate of candidates) {
|
|
349
|
+
this.delete(candidate.key);
|
|
350
|
+
// If we reached our target (buffer or just space), we stop.
|
|
351
|
+
if (isTargetReached(aimForBuffer)) {
|
|
352
|
+
logGC("Step 2 (Importance) finished", { level });
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
// 3. Strategy: Delete biggest items
|
|
358
|
+
// If we are still here, it means we have high importance items filling the cache.
|
|
359
|
+
// We try to free space by removing the largest items first.
|
|
360
|
+
if (!isTargetReached(false)) {
|
|
361
|
+
let b1 = null;
|
|
362
|
+
let b2 = null;
|
|
363
|
+
let b3 = null;
|
|
364
|
+
for (const entry of this._storage.values()) {
|
|
365
|
+
if (!b1 || entry.size > b1.size) {
|
|
366
|
+
b3 = b2;
|
|
367
|
+
b2 = b1;
|
|
368
|
+
b1 = entry;
|
|
369
|
+
}
|
|
370
|
+
else if (!b2 || entry.size > b2.size) {
|
|
371
|
+
b3 = b2;
|
|
372
|
+
b2 = entry;
|
|
373
|
+
}
|
|
374
|
+
else if (!b3 || entry.size > b3.size) {
|
|
375
|
+
b3 = entry;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
if (b1) {
|
|
379
|
+
this.delete(b1.key);
|
|
380
|
+
if (isTargetReached(false)) {
|
|
381
|
+
logGC("Step 3 (Biggest) finished");
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
if (b2) {
|
|
386
|
+
this.delete(b2.key);
|
|
387
|
+
if (isTargetReached(false)) {
|
|
388
|
+
logGC("Step 3 (Biggest) finished");
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (b3) {
|
|
393
|
+
this.delete(b3.key);
|
|
394
|
+
if (isTargetReached(false)) {
|
|
395
|
+
logGC("Step 3 (Biggest) finished");
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
// 4. Fallback / Emergency
|
|
401
|
+
if (!isTargetReached(false)) {
|
|
402
|
+
const iterator = this._storage.keys();
|
|
403
|
+
let result = iterator.next();
|
|
404
|
+
while (!result.done) {
|
|
405
|
+
this.delete(result.value);
|
|
406
|
+
if (isTargetReached(false)) {
|
|
407
|
+
logGC("Step 4 (Fallback) finished");
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
result = iterator.next();
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jk_memcache/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,12 @@ export interface ValueWithPriority<T> {
|
|
|
17
17
|
value: T;
|
|
18
18
|
priority: PriorityLevel;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Sorts a list of items based on their priority level in ascending order.
|
|
22
|
+
* Items with lower priority values (e.g., -200) will appear first in the returned array.
|
|
23
|
+
* @param values The list of items to sort, each containing a value and a priority.
|
|
24
|
+
* @returns An array of just the values, sorted by priority. Returns undefined if the input is undefined.
|
|
25
|
+
*/
|
|
20
26
|
export declare function sortByPriority<T>(values: undefined | ValueWithPriority<T>[]): undefined | (T[]);
|
|
21
27
|
/**
|
|
22
28
|
* Allows avoiding calling a function before n-milliseconds is elapsed.
|
package/dist/jk_tools/common.js
CHANGED
|
@@ -57,6 +57,12 @@ export var PriorityLevel;
|
|
|
57
57
|
PriorityLevel[PriorityLevel["high"] = 100] = "high";
|
|
58
58
|
PriorityLevel[PriorityLevel["veryHigh"] = 200] = "veryHigh";
|
|
59
59
|
})(PriorityLevel || (PriorityLevel = {}));
|
|
60
|
+
/**
|
|
61
|
+
* Sorts a list of items based on their priority level in ascending order.
|
|
62
|
+
* Items with lower priority values (e.g., -200) will appear first in the returned array.
|
|
63
|
+
* @param values The list of items to sort, each containing a value and a priority.
|
|
64
|
+
* @returns An array of just the values, sorted by priority. Returns undefined if the input is undefined.
|
|
65
|
+
*/
|
|
60
66
|
export function sortByPriority(values) {
|
|
61
67
|
if (values === undefined)
|
|
62
68
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/jk_tools/common.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/jk_tools/common.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.1.
|
|
2
|
+
"version": "3.1.32",
|
|
3
3
|
"name": "jopi-toolkit",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"homepage": "https://github.com/johanpiquet/jopi-toolkit",
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
20
|
"jopiLink": "npx jopi-mono link-add",
|
|
21
|
-
"bunLink": "bun link",
|
|
22
21
|
"dev:build": "tsc",
|
|
23
22
|
"dev:tsc-watch": "tsc --watch",
|
|
24
23
|
"dev:tsc-check": "tsc --noEmit"
|
|
@@ -33,8 +32,8 @@
|
|
|
33
32
|
"mime-types": "^3.0.1",
|
|
34
33
|
"ws": "^8.18.3"
|
|
35
34
|
},
|
|
36
|
-
"publishedDate": "1/
|
|
37
|
-
"publicPublishedDate": "1/
|
|
35
|
+
"publishedDate": "1/21/2026",
|
|
36
|
+
"publicPublishedDate": "1/21/2026",
|
|
38
37
|
"exports": {
|
|
39
38
|
"./jk_schema": {
|
|
40
39
|
"types": "./src/jk_schemas/index.ts",
|
|
@@ -115,6 +114,11 @@
|
|
|
115
114
|
"types": "./src/jk_logs/index.ts",
|
|
116
115
|
"bun": "./src/jk_logs/index.ts",
|
|
117
116
|
"default": "./dist/jk_logs/index.js"
|
|
117
|
+
},
|
|
118
|
+
"./jk_memcache": {
|
|
119
|
+
"types": "./src/jk_memcache/index.ts",
|
|
120
|
+
"bun": "./src/jk_memcache/index.ts",
|
|
121
|
+
"default": "./dist/jk_memcache/index.js"
|
|
118
122
|
}
|
|
119
123
|
}
|
|
120
124
|
}
|
package/src/jk_logs/index.ts
CHANGED
|
@@ -51,7 +51,7 @@ export const formater_dateTypeTitleSourceData: LogEntryFormater = (entry: LogEnt
|
|
|
51
51
|
const date = formatDate1(entry.date);
|
|
52
52
|
|
|
53
53
|
let json = entry.data ? JSON.stringify(entry.data) : "";
|
|
54
|
-
const title = (entry.title || "").padEnd(50, " ");
|
|
54
|
+
const title = String(entry.title || "").padEnd(50, " ");
|
|
55
55
|
|
|
56
56
|
json = entry.logger + " |>" + json;
|
|
57
57
|
|
|
@@ -71,7 +71,7 @@ export const formater_dateTypeTitleSourceData: LogEntryFormater = (entry: LogEnt
|
|
|
71
71
|
|
|
72
72
|
export const formater_typeTitleSourceData_colored: LogEntryFormater = (entry: LogEntry) => {
|
|
73
73
|
let json = entry.data ? JSON.stringify(entry.data) : "";
|
|
74
|
-
const title = (entry.title || "").padEnd(50, " ");
|
|
74
|
+
const title = String(entry.title || "").padEnd(50, " ");
|
|
75
75
|
|
|
76
76
|
json = entry.timeDif === undefined
|
|
77
77
|
? `${entry.logger} ${json}` : `${entry.logger} (${entry.timeDif} ms) ${json}`;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
|
|
2
|
+
# JkMemCache (`jk_memcache`)
|
|
3
|
+
|
|
4
|
+
A robust, in-memory caching system, designed with optimization and memory management in mind.
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- **Store Anything**: Supports `string`, `ArrayBuffer`, and `Object` (automatically serialized).
|
|
9
|
+
- **Memory Management**:
|
|
10
|
+
- **Memory Limit**: Define a maximum size in bytes.
|
|
11
|
+
- **Count Limit**: Define a maximum number of entries.
|
|
12
|
+
- **Garbage Collection (GC)**: Automatic cleanup of expired items and intelligent eviction when full.
|
|
13
|
+
- **Smart Eviction**:
|
|
14
|
+
- **Importance Levels**: Mark entries as critical to prevent them from being discarded easily.
|
|
15
|
+
- **Access Tracking**: Tracks how often items are used to prioritize keeping frequently accessed data.
|
|
16
|
+
- **Expiration**: Support for TTL (Time To Live) and absolute expiration dates.
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
### basic
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { JkMemCache } from '@jopi-toolkit/jk_memcache';
|
|
24
|
+
|
|
25
|
+
// Create a cache with limits
|
|
26
|
+
const cache = new JkMemCache({
|
|
27
|
+
maxCount: 1000, // Max 1000 items
|
|
28
|
+
maxSize: 5 * 1024 * 1024, // Max 5MB
|
|
29
|
+
cleanupInterval: 30000 // Cleanup every 30s
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Store data
|
|
33
|
+
cache.set('user:123', { name: 'John', role: 'admin' }, {
|
|
34
|
+
ttl: 60000, // Expires in 1 minute
|
|
35
|
+
importance: 5 // High importance (default is 1)
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Retrieve data
|
|
39
|
+
const user = cache.get('user:123'); // { name: 'John', ... }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Options
|
|
43
|
+
|
|
44
|
+
#### Constructor Options
|
|
45
|
+
|
|
46
|
+
| Option | Type | Default | Description |
|
|
47
|
+
|yyy|yyy|yyy|yyy|
|
|
48
|
+
| `maxCount` | `number` | `Infinity` | Maximum number of items allowed in the cache. |
|
|
49
|
+
| `maxSize` | `number` | `50MB` | Maximum estimated memory size in bytes. |
|
|
50
|
+
| `cleanupInterval` | `number` | `60000` | Interval (ms) for running the background cleanup (removes expired items). |
|
|
51
|
+
|
|
52
|
+
#### `set(key, value, options)` Options
|
|
53
|
+
|
|
54
|
+
| Option | Type | Default | Description |
|
|
55
|
+
|yyy|yyy|yyy|yyy|
|
|
56
|
+
| `importance` | `number` | `1` | Importance level. Higher values protect the item from eviction when memory is full. |
|
|
57
|
+
| `ttl` | `number` | - | Time To Live in milliseconds. |
|
|
58
|
+
| `expiresAt` | `Date` \| `number` | - | Absolute date when the item expires. |
|
|
59
|
+
|
|
60
|
+
## Eviction Strategy
|
|
61
|
+
|
|
62
|
+
When the cache reaches its memory or count limit, the Garbage Collector runs immediately upon the next `set` operation. It selects victims based on a scoring system:
|
|
63
|
+
|
|
64
|
+
1. **Low Importance**: Items with lower importance are targeted first.
|
|
65
|
+
2. **Low Usage**: Least frequently accessed items are targeted next.
|
|
66
|
+
3. **Age**: Older items are targeted last if importance and usage are equal.
|
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
import { logMemCache } from "./_logs.ts";
|
|
2
|
+
|
|
3
|
+
export interface CacheEntryOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Importance level. Higher value means less likely to be evicted by GC.
|
|
6
|
+
* Default: 1
|
|
7
|
+
*/
|
|
8
|
+
importance?: number;
|
|
9
|
+
/**
|
|
10
|
+
* Time to live in milliseconds.
|
|
11
|
+
*/
|
|
12
|
+
ttl?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Absolute expiration date.
|
|
15
|
+
*/
|
|
16
|
+
expiresAt?: number;
|
|
17
|
+
/**
|
|
18
|
+
* Arbitrary metadata (optional).
|
|
19
|
+
*/
|
|
20
|
+
meta?: any;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface InternalCacheEntry {
|
|
24
|
+
key: string;
|
|
25
|
+
value: string | ArrayBuffer | Uint8Array;
|
|
26
|
+
type: 'string' | 'buffer' | 'json';
|
|
27
|
+
size: number;
|
|
28
|
+
createdAt: number;
|
|
29
|
+
expiresAt: number | null;
|
|
30
|
+
accessCount: number;
|
|
31
|
+
importance: number;
|
|
32
|
+
meta: any;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface JkMemCacheOptions {
|
|
36
|
+
/**
|
|
37
|
+
* Name of the cache instance (used for logs).
|
|
38
|
+
*/
|
|
39
|
+
name: string;
|
|
40
|
+
/**
|
|
41
|
+
* Maximum number of items in cache.
|
|
42
|
+
* Default: Infinity
|
|
43
|
+
*/
|
|
44
|
+
maxCount?: number;
|
|
45
|
+
/**
|
|
46
|
+
* Maximum size in bytes.
|
|
47
|
+
* Default: 50MB (50 * 1024 * 1024)
|
|
48
|
+
*/
|
|
49
|
+
maxSize?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Interval in milliseconds for the recurrent GC.
|
|
52
|
+
* Default: 60000 (1 minute)
|
|
53
|
+
*/
|
|
54
|
+
cleanupInterval?: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class JkMemCache {
|
|
58
|
+
private _storage = new Map<string, InternalCacheEntry>();
|
|
59
|
+
private _currentSize = 0;
|
|
60
|
+
private _options: Required<JkMemCacheOptions>;
|
|
61
|
+
private _intervalId: any = null;
|
|
62
|
+
private _name: string;
|
|
63
|
+
|
|
64
|
+
constructor(options: JkMemCacheOptions) {
|
|
65
|
+
this._options = {
|
|
66
|
+
name: options.name,
|
|
67
|
+
maxCount: options.maxCount ?? Infinity,
|
|
68
|
+
maxSize: options.maxSize ?? 50 * 1024 * 1024,
|
|
69
|
+
cleanupInterval: options.cleanupInterval ?? 60000,
|
|
70
|
+
};
|
|
71
|
+
this._name = options.name;
|
|
72
|
+
|
|
73
|
+
logMemCache.info(`Cache [${this._name}] initialized`);
|
|
74
|
+
|
|
75
|
+
if (this._options.cleanupInterval > 0) {
|
|
76
|
+
this.startAutoCleanup();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Start the automatic cleanup interval.
|
|
82
|
+
*/
|
|
83
|
+
public startAutoCleanup() {
|
|
84
|
+
if (this._intervalId) clearInterval(this._intervalId);
|
|
85
|
+
|
|
86
|
+
this._intervalId = setInterval(() => {
|
|
87
|
+
this.performCleanup();
|
|
88
|
+
}, this._options.cleanupInterval);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Stop the automatic cleanup interval.
|
|
93
|
+
*/
|
|
94
|
+
public stopAutoCleanup() {
|
|
95
|
+
if (this._intervalId) {
|
|
96
|
+
clearInterval(this._intervalId);
|
|
97
|
+
this._intervalId = null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Add or update an item in the cache.
|
|
103
|
+
*/
|
|
104
|
+
public set(key: string, value: string | ArrayBuffer | Uint8Array | object, options: CacheEntryOptions = {}) {
|
|
105
|
+
// 1. Prepare new entry details
|
|
106
|
+
let storedValue: string | ArrayBuffer | Uint8Array;
|
|
107
|
+
let type: 'string' | 'buffer' | 'json';
|
|
108
|
+
let size = 0;
|
|
109
|
+
|
|
110
|
+
// Meta size calculation
|
|
111
|
+
const metaSize = options.meta ? JSON.stringify(options.meta).length * 2 : 0;
|
|
112
|
+
|
|
113
|
+
if (value instanceof ArrayBuffer) {
|
|
114
|
+
storedValue = value;
|
|
115
|
+
type = 'buffer';
|
|
116
|
+
size = value.byteLength;
|
|
117
|
+
} else if (value instanceof Uint8Array) {
|
|
118
|
+
storedValue = value;
|
|
119
|
+
type = 'buffer';
|
|
120
|
+
size = value.byteLength;
|
|
121
|
+
} else if (typeof value === 'string') {
|
|
122
|
+
storedValue = value;
|
|
123
|
+
type = 'string';
|
|
124
|
+
size = value.length * 2; // Approximation for JS string memory
|
|
125
|
+
} else {
|
|
126
|
+
storedValue = JSON.stringify(value);
|
|
127
|
+
type = 'json';
|
|
128
|
+
size = (storedValue as string).length * 2;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Overhead for object structure (approximate) + Meta size
|
|
132
|
+
size += 100 + metaSize;
|
|
133
|
+
|
|
134
|
+
// 2. Check overlap
|
|
135
|
+
if (this._storage.has(key)) {
|
|
136
|
+
this.delete(key);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 3. Calculate Expiration
|
|
140
|
+
|
|
141
|
+
let expiresAt: number | null = null;
|
|
142
|
+
|
|
143
|
+
if (options.expiresAt) {
|
|
144
|
+
expiresAt = options.expiresAt;
|
|
145
|
+
} else if (options.ttl) {
|
|
146
|
+
expiresAt = Date.now() + options.ttl;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const entry: InternalCacheEntry = {
|
|
150
|
+
key,
|
|
151
|
+
value: storedValue,
|
|
152
|
+
type,
|
|
153
|
+
size,
|
|
154
|
+
createdAt: Date.now(),
|
|
155
|
+
expiresAt,
|
|
156
|
+
accessCount: 0,
|
|
157
|
+
importance: options.importance ?? 1,
|
|
158
|
+
meta: options.meta,
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// 4. Check if item is too big for the cache entirely
|
|
162
|
+
if (entry.size > this._options.maxSize) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 5. Check if we need to make space
|
|
167
|
+
if (this.needsEviction(entry.size)) {
|
|
168
|
+
this.evictFor(entry.size);
|
|
169
|
+
|
|
170
|
+
if (this.needsEviction(entry.size)) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
this._storage.set(key, entry);
|
|
176
|
+
this._currentSize += size;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Retrieve an item from the cache.
|
|
181
|
+
*/
|
|
182
|
+
public get<T = any>(key: string, peek = false): T | null {
|
|
183
|
+
const entry = this._storage.get(key);
|
|
184
|
+
if (!entry) return null;
|
|
185
|
+
|
|
186
|
+
if (entry.expiresAt && entry.expiresAt < Date.now()) {
|
|
187
|
+
this.delete(key);
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (!peek) entry.accessCount++;
|
|
192
|
+
|
|
193
|
+
if (entry.type === 'buffer') {
|
|
194
|
+
return entry.value as T;
|
|
195
|
+
} else if (entry.type === 'json') {
|
|
196
|
+
return JSON.parse(entry.value as string) as T;
|
|
197
|
+
} else {
|
|
198
|
+
return entry.value as T;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Retrieve an item from the cache with its metadata.
|
|
204
|
+
*/
|
|
205
|
+
public getWithMeta<T = any>(key: string, peek = false): { value: T; meta: any } | null {
|
|
206
|
+
const entry = this._storage.get(key);
|
|
207
|
+
if (!entry) return null;
|
|
208
|
+
|
|
209
|
+
if (entry.expiresAt && entry.expiresAt < Date.now()) {
|
|
210
|
+
this.delete(key);
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (!peek) entry.accessCount++;
|
|
215
|
+
|
|
216
|
+
let value: T;
|
|
217
|
+
if (entry.type === 'buffer') {
|
|
218
|
+
value = entry.value as T;
|
|
219
|
+
} else if (entry.type === 'json') {
|
|
220
|
+
value = JSON.parse(entry.value as string) as T;
|
|
221
|
+
} else {
|
|
222
|
+
value = entry.value as T;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return { value, meta: entry.meta };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Check if an item exists in the cache and is not expired.
|
|
230
|
+
* Does not increment accessCount.
|
|
231
|
+
*/
|
|
232
|
+
public has(key: string): boolean {
|
|
233
|
+
const entry = this._storage.get(key);
|
|
234
|
+
if (!entry) return false;
|
|
235
|
+
|
|
236
|
+
if (entry.expiresAt && entry.expiresAt < Date.now()) {
|
|
237
|
+
this.delete(key);
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Manually delete an item.
|
|
246
|
+
*/
|
|
247
|
+
public delete(key: string) {
|
|
248
|
+
const entry = this._storage.get(key);
|
|
249
|
+
|
|
250
|
+
if (entry) {
|
|
251
|
+
this._currentSize -= entry.size;
|
|
252
|
+
this._storage.delete(key);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Clear all items.
|
|
258
|
+
*/
|
|
259
|
+
public clear() {
|
|
260
|
+
this._storage.clear();
|
|
261
|
+
this._currentSize = 0;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Get current cache stats.
|
|
266
|
+
*/
|
|
267
|
+
public getStats() {
|
|
268
|
+
return {
|
|
269
|
+
count: this._storage.size,
|
|
270
|
+
size: this._currentSize,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Iterate over all valid keys.
|
|
276
|
+
*/
|
|
277
|
+
public *keys(): Generator<string> {
|
|
278
|
+
const now = Date.now();
|
|
279
|
+
for (const [key, entry] of this._storage) {
|
|
280
|
+
if (entry.expiresAt && now > entry.expiresAt) {
|
|
281
|
+
this.delete(key);
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
yield key;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Iterate over keys starting with a prefix.
|
|
290
|
+
*/
|
|
291
|
+
public *keysStartingWith(prefix: string): Generator<string> {
|
|
292
|
+
for (const key of this.keys()) {
|
|
293
|
+
if (key.startsWith(prefix)) yield key;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Iterate over keys ending with a suffix.
|
|
299
|
+
*/
|
|
300
|
+
public *keysEndingWith(suffix: string): Generator<string> {
|
|
301
|
+
for (const key of this.keys()) {
|
|
302
|
+
if (key.endsWith(suffix)) yield key;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Iterate over keys containing a specific text.
|
|
308
|
+
*/
|
|
309
|
+
public *keysContaining(text: string): Generator<string> {
|
|
310
|
+
for (const key of this.keys()) {
|
|
311
|
+
if (key.includes(text)) yield key;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Check if we need to evict entries to fit a new one (or if limits are exceeded).
|
|
317
|
+
*/
|
|
318
|
+
private needsEviction(incomingSize: number): boolean {
|
|
319
|
+
return (
|
|
320
|
+
(this._storage.size + 1 > this._options.maxCount) ||
|
|
321
|
+
(this._currentSize + incomingSize > this._options.maxSize)
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Perform recurrent cleanup (expiration only).
|
|
327
|
+
*/
|
|
328
|
+
private performCleanup() {
|
|
329
|
+
const now = Date.now();
|
|
330
|
+
let removedCount = 0;
|
|
331
|
+
|
|
332
|
+
logMemCache.info(`Cache [${this._name}] Recurrent GC started - ${JSON.stringify({
|
|
333
|
+
count: this._storage.size,
|
|
334
|
+
sizeMB: (this._currentSize / 1024 / 1024).toFixed(2)
|
|
335
|
+
})}`);
|
|
336
|
+
|
|
337
|
+
for (const [key, entry] of this._storage) {
|
|
338
|
+
if (entry.expiresAt && now > entry.expiresAt) {
|
|
339
|
+
this.delete(key);
|
|
340
|
+
removedCount++;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (removedCount > 0) {
|
|
345
|
+
logMemCache.info(`Cache [${this._name}] Recurrent GC finished - ${JSON.stringify({
|
|
346
|
+
removed: removedCount,
|
|
347
|
+
remaining: this._storage.size,
|
|
348
|
+
sizeMB: (this._currentSize / 1024 / 1024).toFixed(2)
|
|
349
|
+
})}`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Evict items to make space/reduce count.
|
|
355
|
+
* Strategy: Calculate a score. Lower score = evicted first.
|
|
356
|
+
* Factors:
|
|
357
|
+
* - expired (immediate kill)
|
|
358
|
+
* - importance (higher = keep)
|
|
359
|
+
* - accessCount (higher = keep)
|
|
360
|
+
*
|
|
361
|
+
* Score = (importance * 1000) + (accessCount)
|
|
362
|
+
* (Simplified logic)
|
|
363
|
+
*/
|
|
364
|
+
private evictFor(requiredSpace: number) {
|
|
365
|
+
const now = Date.now();
|
|
366
|
+
|
|
367
|
+
logMemCache.info(`Cache [${this._name}] GC Eviction started (Memory Pressure) - ${JSON.stringify({
|
|
368
|
+
requiredSpace,
|
|
369
|
+
count: this._storage.size,
|
|
370
|
+
sizeMB: (this._currentSize / 1024 / 1024).toFixed(2)
|
|
371
|
+
})}`);
|
|
372
|
+
|
|
373
|
+
// 1. Remove expired first (In-place, no allocation)
|
|
374
|
+
for (const [key, entry] of this._storage) {
|
|
375
|
+
if (entry.expiresAt && now > entry.expiresAt) {
|
|
376
|
+
this.delete(key);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Optimization: Low Water Mark.
|
|
381
|
+
// To avoid frequent GC, when we evict, we try to go down to 90% capacity,
|
|
382
|
+
// creating a temporary buffer.
|
|
383
|
+
//
|
|
384
|
+
const safeSize = this._options.maxSize * 0.9;
|
|
385
|
+
const safeCount = this._options.maxCount * 0.9;
|
|
386
|
+
|
|
387
|
+
// Helper: Have we reached our goal?
|
|
388
|
+
// If strict is true, we aim for the buffer (90%).
|
|
389
|
+
// If strict is false, we just aim to fit the item (100%).
|
|
390
|
+
const isTargetReached = (strict: boolean) => {
|
|
391
|
+
// 1. Absolute requirement: Must fit the new item within MAX limits.
|
|
392
|
+
// needsEviction returns TRUE if we are OVER limits.
|
|
393
|
+
if (this.needsEviction(requiredSpace)) {
|
|
394
|
+
return false; // We are over max, so target is definitely NOT reached.
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// 2. Buffer requirement: specific to strict mode
|
|
398
|
+
if (strict) {
|
|
399
|
+
// We are under MAX, but are we under SAFE limits?
|
|
400
|
+
return (this._currentSize + requiredSpace <= safeSize) && (this._storage.size <= safeCount);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// If not strict, and needsEviction was false, we are good.
|
|
404
|
+
return true;
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
// Helper to format log message
|
|
408
|
+
const logGC = (step: string, extra: object = {}) => {
|
|
409
|
+
logMemCache.info(`Cache [${this._name}] [GC] ${step} - ${JSON.stringify({
|
|
410
|
+
...extra,
|
|
411
|
+
count: this._storage.size,
|
|
412
|
+
sizeMB: (this._currentSize / 1024 / 1024).toFixed(2)
|
|
413
|
+
})}`);
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
if (isTargetReached(true)) {
|
|
417
|
+
logGC("Step 1 (Expired) sufficient");
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// 2. Multi-step Eviction by Importance
|
|
422
|
+
const MAX_SEARCH_LEVEL = 10;
|
|
423
|
+
// We treat levels 1-5 as "recyclable" to build buffer.
|
|
424
|
+
// Levels 6-10 are "protected" -> only evicted if absolutely necessary to fit the item.
|
|
425
|
+
const BUFFER_TARGET_LEVEL = 5;
|
|
426
|
+
|
|
427
|
+
for (let level = 1; level <= MAX_SEARCH_LEVEL; level++) {
|
|
428
|
+
const candidates: InternalCacheEntry[] = [];
|
|
429
|
+
|
|
430
|
+
for (const entry of this._storage.values()) {
|
|
431
|
+
if (entry.importance === level) {
|
|
432
|
+
candidates.push(entry);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (candidates.length === 0) continue;
|
|
437
|
+
|
|
438
|
+
candidates.sort((a, b) => {
|
|
439
|
+
if (a.accessCount !== b.accessCount) {
|
|
440
|
+
return a.accessCount - b.accessCount;
|
|
441
|
+
}
|
|
442
|
+
return a.createdAt - b.createdAt;
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
const aimForBuffer = level <= BUFFER_TARGET_LEVEL;
|
|
446
|
+
|
|
447
|
+
for (const candidate of candidates) {
|
|
448
|
+
this.delete(candidate.key);
|
|
449
|
+
// If we reached our target (buffer or just space), we stop.
|
|
450
|
+
if (isTargetReached(aimForBuffer)) {
|
|
451
|
+
logGC("Step 2 (Importance) finished", { level });
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// 3. Strategy: Delete biggest items
|
|
458
|
+
// If we are still here, it means we have high importance items filling the cache.
|
|
459
|
+
// We try to free space by removing the largest items first.
|
|
460
|
+
if (!isTargetReached(false)) {
|
|
461
|
+
let b1: InternalCacheEntry | null = null;
|
|
462
|
+
let b2: InternalCacheEntry | null = null;
|
|
463
|
+
let b3: InternalCacheEntry | null = null;
|
|
464
|
+
|
|
465
|
+
for (const entry of this._storage.values()) {
|
|
466
|
+
if (!b1 || entry.size > b1.size) {
|
|
467
|
+
b3 = b2;
|
|
468
|
+
b2 = b1;
|
|
469
|
+
b1 = entry;
|
|
470
|
+
} else if (!b2 || entry.size > b2.size) {
|
|
471
|
+
b3 = b2;
|
|
472
|
+
b2 = entry;
|
|
473
|
+
} else if (!b3 || entry.size > b3.size) {
|
|
474
|
+
b3 = entry;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
if (b1) { this.delete(b1.key); if (isTargetReached(false)) { logGC("Step 3 (Biggest) finished"); return; } }
|
|
479
|
+
if (b2) { this.delete(b2.key); if (isTargetReached(false)) { logGC("Step 3 (Biggest) finished"); return; } }
|
|
480
|
+
if (b3) { this.delete(b3.key); if (isTargetReached(false)) { logGC("Step 3 (Biggest) finished"); return; } }
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// 4. Fallback / Emergency
|
|
484
|
+
if (!isTargetReached(false)) {
|
|
485
|
+
const iterator = this._storage.keys();
|
|
486
|
+
let result = iterator.next();
|
|
487
|
+
|
|
488
|
+
while (!result.done) {
|
|
489
|
+
this.delete(result.value);
|
|
490
|
+
if (isTargetReached(false)) {
|
|
491
|
+
logGC("Step 4 (Fallback) finished");
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
result = iterator.next();
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
package/src/jk_tools/common.ts
CHANGED
|
@@ -69,6 +69,12 @@ export interface ValueWithPriority<T> {
|
|
|
69
69
|
priority: PriorityLevel;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Sorts a list of items based on their priority level in ascending order.
|
|
74
|
+
* Items with lower priority values (e.g., -200) will appear first in the returned array.
|
|
75
|
+
* @param values The list of items to sort, each containing a value and a priority.
|
|
76
|
+
* @returns An array of just the values, sorted by priority. Returns undefined if the input is undefined.
|
|
77
|
+
*/
|
|
72
78
|
export function sortByPriority<T>(values: undefined|ValueWithPriority<T>[]): undefined|(T[]) {
|
|
73
79
|
if (values === undefined) return undefined;
|
|
74
80
|
|