@hyperttp/cache 1.1.1 → 1.1.5
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/README.md +0 -5
- package/package.json +10 -6
- package/plugin.d.ts +45 -5
- package/plugin.d.ts.map +1 -1
- package/plugin.js +101 -101
- package/plugin.js.map +1 -1
- package/types/cache.d.ts +60 -8
- package/types/cache.d.ts.map +1 -1
- package/utils/CacheManager.d.ts +37 -44
- package/utils/CacheManager.d.ts.map +1 -1
- package/utils/CacheManager.js +102 -54
- package/utils/CacheManager.js.map +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
```markdown
|
|
2
1
|
# hyperttp-cache
|
|
3
2
|
|
|
4
3
|
> [Русский](https://github.com/IT-IF-OR/hyperttp-cache/tree/main/lang/ru) | English
|
|
@@ -136,7 +135,3 @@ from the map to ensure subsequent retries targeting the failed endpoint are neve
|
|
|
136
135
|
## 📄 License
|
|
137
136
|
|
|
138
137
|
MIT
|
|
139
|
-
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
```
|
package/package.json
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperttp/cache",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "High-performance LRU caching plugin for Hyperttp client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
7
7
|
"types": "./index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./index.d.ts",
|
|
11
|
+
"import": "./index.js",
|
|
12
|
+
"require": "./index.js"
|
|
13
|
+
},
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
8
16
|
"keywords": [
|
|
9
17
|
"hyperttp"
|
|
10
18
|
],
|
|
@@ -14,12 +22,8 @@
|
|
|
14
22
|
"type": "git",
|
|
15
23
|
"url": "git+https://github.com/IT-IF-OR/hyperttp-cache.git"
|
|
16
24
|
},
|
|
17
|
-
"dependencies": {
|
|
18
|
-
"@hyperttp/types": "^0.1.1",
|
|
19
|
-
"lru-cache": "^11.5.1"
|
|
20
|
-
},
|
|
21
25
|
"peerDependencies": {
|
|
22
|
-
"@hyperttp/
|
|
26
|
+
"@hyperttp/types": "^0.1.5"
|
|
23
27
|
},
|
|
24
28
|
"private": false
|
|
25
29
|
}
|
package/plugin.d.ts
CHANGED
|
@@ -1,24 +1,64 @@
|
|
|
1
1
|
import type { HyperPlugin } from "@hyperttp/types";
|
|
2
|
-
import type { CacheManagerOptions } from "./types/cache.js";
|
|
2
|
+
import type { CacheManagerOptions, LightweightResponse } from "./types/cache.js";
|
|
3
3
|
import { CacheManager } from "./utils/CacheManager.js";
|
|
4
|
+
/**
|
|
5
|
+
* @en Extends the PluginContext to include the cache manager instance.
|
|
6
|
+
* @ru Расширяет PluginContext, добавляя экземпляр менеджера кэша.
|
|
7
|
+
*/
|
|
4
8
|
declare module "@hyperttp/types" {
|
|
5
9
|
interface PluginContext {
|
|
6
|
-
|
|
10
|
+
/**
|
|
11
|
+
* @en The active cache manager instance.
|
|
12
|
+
* @ru Активный экземпляр менеджера кэша.
|
|
13
|
+
*/
|
|
14
|
+
cache?: CacheManager<LightweightResponse>;
|
|
7
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* @en Extends HyperttpPluginsExtension to include cache configuration options.
|
|
18
|
+
* @ru Расширяет HyperttpPluginsExtension, добавляя опции конфигурации кэша.
|
|
19
|
+
*/
|
|
8
20
|
interface HyperttpPluginsExtension {
|
|
21
|
+
/**
|
|
22
|
+
* @en Cache configuration and enablement flags.
|
|
23
|
+
* @ru Конфигурация кэша и флаги включения.
|
|
24
|
+
*/
|
|
9
25
|
cache?: CacheManagerOptions & {
|
|
26
|
+
/**
|
|
27
|
+
* @en Enables or disables the caching plugin.
|
|
28
|
+
* @ru Включает или отключает плагин кэширования.
|
|
29
|
+
*/
|
|
10
30
|
enabled: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* @en List of HTTP methods allowed for caching (e.g., ["GET"]).
|
|
33
|
+
* @ru Список HTTP-методов, разрешенных для кэширования (например, ["GET"]).
|
|
34
|
+
*/
|
|
35
|
+
methods?: string[];
|
|
11
36
|
};
|
|
12
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* @en Extends IHyperCore with cache management methods.
|
|
40
|
+
* @ru Расширяет IHyperCore методами управления кэшем.
|
|
41
|
+
*/
|
|
13
42
|
interface IHyperCore {
|
|
43
|
+
/**
|
|
44
|
+
* @en Clears the cache. If a key is provided, only that entry is removed.
|
|
45
|
+
* @ru Очищает кэш. Если указан ключ, удаляется только соответствующая запись.
|
|
46
|
+
* @param key - Optional cache key to delete.
|
|
47
|
+
*/
|
|
14
48
|
clearCache(key?: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* @en Returns runtime statistics, including cache size.
|
|
51
|
+
* @ru Возвращает статистику выполнения, включая размер кэша.
|
|
52
|
+
*/
|
|
15
53
|
getStats?(): Record<string, any>;
|
|
16
54
|
}
|
|
17
55
|
}
|
|
18
56
|
/**
|
|
19
|
-
* @
|
|
20
|
-
*
|
|
21
|
-
* @
|
|
57
|
+
* @en Creates a caching plugin for Hyperttp.
|
|
58
|
+
* Handles in-memory caching, conditional requests (ETag/Last-Modified), and request deduplication.
|
|
59
|
+
* @ru Создает плагин кэширования для Hyperttp.
|
|
60
|
+
* Обрабатывает кэширование в памяти, условные запросы (ETag/Last-Modified) и дедупликацию запросов.
|
|
61
|
+
* @returns The configured HyperPlugin instance.
|
|
22
62
|
*/
|
|
23
63
|
export declare function withCache(): HyperPlugin;
|
|
24
64
|
//# sourceMappingURL=plugin.d.ts.map
|
package/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,WAAW,
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,WAAW,EAIZ,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD;;;GAGG;AACH,OAAO,QAAQ,iBAAiB,CAAC;IAC/B,UAAU,aAAa;QACrB;;;WAGG;QACH,KAAK,CAAC,EAAE,YAAY,CAAC,mBAAmB,CAAC,CAAC;KAC3C;IAED;;;OAGG;IACH,UAAU,wBAAwB;QAChC;;;WAGG;QACH,KAAK,CAAC,EAAE,mBAAmB,GAAG;YAC5B;;;eAGG;YACH,OAAO,EAAE,OAAO,CAAC;YACjB;;;eAGG;YACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;SACpB,CAAC;KACH;IAED;;;OAGG;IACH,UAAU,UAAU;QAClB;;;;WAIG;QACH,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAE/B;;;WAGG;QACH,QAAQ,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAClC;CACF;AA0BD;;;;;;GAMG;AACH,wBAAgB,SAAS,IAAI,WAAW,CAyKvC"}
|
package/plugin.js
CHANGED
|
@@ -1,92 +1,76 @@
|
|
|
1
1
|
import { CacheManager } from "./utils/CacheManager.js";
|
|
2
2
|
/**
|
|
3
|
-
* @
|
|
4
|
-
* @
|
|
5
|
-
* @
|
|
3
|
+
* @en Helper function to create a standardized HttpResponse object from lightweight data.
|
|
4
|
+
* @ru Вспомогательная функция для создания стандартизированного объекта HttpResponse из легких данных.
|
|
5
|
+
* @param data - The lightweight response data.
|
|
6
|
+
* @returns A full HttpResponse object.
|
|
7
|
+
*/
|
|
8
|
+
const createHttpResponse = (data) => ({
|
|
9
|
+
status: data.status,
|
|
10
|
+
headers: data.headers,
|
|
11
|
+
body: data.body,
|
|
12
|
+
url: data.url,
|
|
13
|
+
clone: () => createHttpResponse(data),
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* @en Creates a caching plugin for Hyperttp.
|
|
17
|
+
* Handles in-memory caching, conditional requests (ETag/Last-Modified), and request deduplication.
|
|
18
|
+
* @ru Создает плагин кэширования для Hyperttp.
|
|
19
|
+
* Обрабатывает кэширование в памяти, условные запросы (ETag/Last-Modified) и дедупликацию запросов.
|
|
20
|
+
* @returns The configured HyperPlugin instance.
|
|
6
21
|
*/
|
|
7
22
|
export function withCache() {
|
|
8
|
-
/**
|
|
9
|
-
* @private
|
|
10
|
-
* @ru Изолированный инстанс менеджера кэша для текущего клиента.
|
|
11
|
-
* @en Isolated cache manager orchestration instance allocated for the target client.
|
|
12
|
-
*/
|
|
13
23
|
let cache;
|
|
14
|
-
|
|
15
|
-
* @private
|
|
16
|
-
* @ru Список HTTP-методов, для которых разрешено кэширование ответов.
|
|
17
|
-
* @en Set of HTTP request methods authorized for downstream response caching.
|
|
18
|
-
*/
|
|
19
|
-
let allowedMethods;
|
|
20
|
-
/**
|
|
21
|
-
* @private
|
|
22
|
-
* @ru Карта активных сетевых запросов для предотвращения каскадного заваливания бэкенда (Cache Stampede).
|
|
23
|
-
* @en Registry of concurrent requests in execution to prevent backend server breakdown (Cache Stampede).
|
|
24
|
-
*/
|
|
24
|
+
let allowedMethods = new Set();
|
|
25
25
|
const inFlight = new Map();
|
|
26
26
|
return {
|
|
27
27
|
name: "hyperttp-cache",
|
|
28
|
-
/**
|
|
29
|
-
* @ru Динамическая проверка необходимости активации кэширования на основе переданных опций.
|
|
30
|
-
* @en Dynamic check evaluating if the caching plugin layer should be appended based on client runtime options.
|
|
31
|
-
* @param config - Глобальная конфигурация инстанса клиента. / Global active client lifecycle options.
|
|
32
|
-
* @returns Индикатор необходимости сборки плагина. / Lifecycle activation indicator status.
|
|
33
|
-
*/
|
|
34
28
|
enabled: (config) => {
|
|
35
29
|
return !!config.cache?.enabled;
|
|
36
30
|
},
|
|
37
|
-
/**
|
|
38
|
-
* @ru Однократный хук инициализации. Настраивает менеджер кэша и внедряет методы отладки/очистки в ядро.
|
|
39
|
-
* @en One-time setup context hook. Orchestrates the cache manager and extends telemetry/purge interfaces inside the core.
|
|
40
|
-
* @param ctx - Общий контекст окружения плагина. / Shared plugin execution context metadata.
|
|
41
|
-
*/
|
|
42
31
|
setup(ctx) {
|
|
43
|
-
const
|
|
32
|
+
const core = ctx.core;
|
|
33
|
+
const config = ctx.config;
|
|
44
34
|
cache = new CacheManager(config?.cache);
|
|
45
35
|
ctx.cache = cache;
|
|
46
36
|
const methods = config?.cache?.methods ?? ["GET"];
|
|
47
37
|
allowedMethods = new Set(methods.map((m) => m.toUpperCase()));
|
|
48
38
|
if (core && typeof core.getStats === "function") {
|
|
49
|
-
const originalGetStats = core.getStats;
|
|
39
|
+
const originalGetStats = core.getStats.bind(core);
|
|
50
40
|
core.getStats = function () {
|
|
51
|
-
const stats = originalGetStats
|
|
52
|
-
|
|
53
|
-
stats
|
|
54
|
-
|
|
55
|
-
|
|
41
|
+
const stats = originalGetStats();
|
|
42
|
+
return {
|
|
43
|
+
...stats,
|
|
44
|
+
cacheSize: cache.size,
|
|
45
|
+
};
|
|
56
46
|
};
|
|
57
47
|
}
|
|
58
48
|
core.clearCache = (key) => {
|
|
59
|
-
|
|
49
|
+
if (key) {
|
|
50
|
+
cache.delete(key);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
cache.clear();
|
|
54
|
+
}
|
|
60
55
|
};
|
|
61
56
|
},
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
* @en Request phase interceptor. Evaluates local cache hits, appends conditional headers, or hooks into active in-flight targets.
|
|
65
|
-
* @param req - Сконфигурированный внутренний объект запроса. / Contextual internal request parameters.
|
|
66
|
-
* @param ctx - Общий контекст окружения плагина. / Shared plugin execution context metadata.
|
|
67
|
-
* @returns Мгновенный изолированный ответ из кэша, обертку гонки или void для продолжения сетевого цикла. / Short-circuit response clone, matching follower promise tracker, or void execution.
|
|
68
|
-
*/
|
|
69
|
-
onRequest(req,
|
|
70
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
71
|
-
_ctx) {
|
|
72
|
-
const method = req.method.toUpperCase();
|
|
73
|
-
if (!allowedMethods.has(method)) {
|
|
57
|
+
onRequest(req) {
|
|
58
|
+
if (!allowedMethods.has(req.method.toUpperCase())) {
|
|
74
59
|
return;
|
|
75
60
|
}
|
|
76
61
|
const cacheKey = req.url;
|
|
77
62
|
const cachedEntry = cache.getWithMetadata(cacheKey);
|
|
78
|
-
if (cachedEntry
|
|
79
|
-
|
|
80
|
-
!cachedEntry.lastModified) {
|
|
81
|
-
return cachedEntry.data.clone();
|
|
63
|
+
if (cachedEntry && !cachedEntry.etag && !cachedEntry.lastModified) {
|
|
64
|
+
return createHttpResponse(cachedEntry.data);
|
|
82
65
|
}
|
|
83
|
-
|
|
84
|
-
if (cachedEntry !== undefined) {
|
|
66
|
+
if (cachedEntry) {
|
|
85
67
|
req.headers = { ...req.headers };
|
|
86
|
-
if (cachedEntry.etag)
|
|
68
|
+
if (cachedEntry.etag) {
|
|
87
69
|
req.headers["if-none-match"] = cachedEntry.etag;
|
|
88
|
-
|
|
70
|
+
}
|
|
71
|
+
if (cachedEntry.lastModified) {
|
|
89
72
|
req.headers["if-modified-since"] = cachedEntry.lastModified;
|
|
73
|
+
}
|
|
90
74
|
}
|
|
91
75
|
const currentInFlight = inFlight.get(cacheKey);
|
|
92
76
|
if (currentInFlight) {
|
|
@@ -94,62 +78,78 @@ export function withCache() {
|
|
|
94
78
|
}
|
|
95
79
|
let resolveFn;
|
|
96
80
|
let rejectFn;
|
|
97
|
-
const promise = new Promise((
|
|
98
|
-
resolveFn =
|
|
99
|
-
rejectFn =
|
|
81
|
+
const promise = new Promise((resolve, reject) => {
|
|
82
|
+
resolveFn = resolve;
|
|
83
|
+
rejectFn = reject;
|
|
100
84
|
});
|
|
101
|
-
|
|
102
|
-
|
|
85
|
+
const trigger = {
|
|
86
|
+
promise,
|
|
87
|
+
resolve: resolveFn,
|
|
88
|
+
reject: (err) => {
|
|
89
|
+
inFlight.delete(cacheKey);
|
|
90
|
+
rejectFn(err);
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
inFlight.set(cacheKey, trigger);
|
|
94
|
+
setTimeout(() => {
|
|
95
|
+
if (inFlight.has(cacheKey)) {
|
|
96
|
+
console.warn(`[Cache] Warning: Request hung for ${cacheKey}, forcing cleanup`);
|
|
97
|
+
trigger.reject(new Error("Request timed out in cache plugin"));
|
|
98
|
+
}
|
|
99
|
+
}, 30_000);
|
|
100
|
+
return;
|
|
103
101
|
},
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
*/
|
|
108
|
-
onResponse(res, req,
|
|
109
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
110
|
-
_ctx) {
|
|
102
|
+
onResponse(res, req) {
|
|
103
|
+
if (!req)
|
|
104
|
+
return;
|
|
111
105
|
const cacheKey = req.url;
|
|
112
106
|
const trigger = inFlight.get(cacheKey);
|
|
113
|
-
if (!trigger)
|
|
107
|
+
if (!trigger)
|
|
114
108
|
return;
|
|
115
|
-
}
|
|
116
109
|
inFlight.delete(cacheKey);
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
110
|
+
if (res.status === 304) {
|
|
111
|
+
const cachedEntry = cache.getWithMetadata(cacheKey);
|
|
112
|
+
if (cachedEntry) {
|
|
113
|
+
const cachedData = cachedEntry.data;
|
|
114
|
+
const restoredRes = {
|
|
115
|
+
status: cachedData.status,
|
|
116
|
+
headers: cachedData.headers,
|
|
117
|
+
body: cachedData.body,
|
|
118
|
+
url: cachedData.url,
|
|
119
|
+
clone: () => createHttpResponse(cachedData),
|
|
120
|
+
};
|
|
121
|
+
trigger.resolve(restoredRes);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
console.warn(`[Cache] Received 304 for ${cacheKey} but no cache entry found.`);
|
|
126
|
+
}
|
|
124
127
|
}
|
|
125
128
|
if (res.status >= 200 && res.status < 300) {
|
|
126
|
-
const
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
const headers = res.headers || {};
|
|
130
|
+
const lightResponse = {
|
|
131
|
+
body: res.body,
|
|
132
|
+
status: res.status,
|
|
133
|
+
headers: res.headers,
|
|
134
|
+
url: res.url,
|
|
135
|
+
};
|
|
136
|
+
cache.setWithMetadata(cacheKey, lightResponse, {
|
|
137
|
+
etag: Array.isArray(headers["etag"])
|
|
138
|
+
? headers["etag"][0]
|
|
139
|
+
: headers["etag"],
|
|
140
|
+
lastModified: Array.isArray(headers["last-modified"])
|
|
141
|
+
? headers["last-modified"][0]
|
|
142
|
+
: headers["last-modified"],
|
|
133
143
|
});
|
|
134
|
-
trigger.resolve(res.clone());
|
|
135
|
-
return;
|
|
136
144
|
}
|
|
137
145
|
trigger.resolve(res.clone());
|
|
138
146
|
},
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
* @param req - Сконфигурированный внутренний объект запроса. / Contextual internal request parameters.
|
|
144
|
-
* @param ctx - Общий контекст окружения плагина. / Shared plugin execution context metadata.
|
|
145
|
-
*/
|
|
146
|
-
onError(err, req,
|
|
147
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
148
|
-
_ctx) {
|
|
149
|
-
const cacheKey = req.url;
|
|
150
|
-
const trigger = inFlight.get(cacheKey);
|
|
147
|
+
onError(err, req) {
|
|
148
|
+
if (!req)
|
|
149
|
+
return;
|
|
150
|
+
const trigger = inFlight.get(req.url);
|
|
151
151
|
if (trigger) {
|
|
152
|
-
inFlight.delete(
|
|
152
|
+
inFlight.delete(req.url);
|
|
153
153
|
trigger.reject(err);
|
|
154
154
|
}
|
|
155
155
|
},
|
package/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
|
package/types/cache.d.ts
CHANGED
|
@@ -1,29 +1,81 @@
|
|
|
1
1
|
import { Method } from "@hyperttp/types";
|
|
2
|
+
/**
|
|
3
|
+
* @en Structure representing a cached item with optional HTTP validation metadata.
|
|
4
|
+
* @ru Структура, представляющая элемент кэша с опциональными метаданными для HTTP-валидации.
|
|
5
|
+
* @template T - Type of the cached data.
|
|
6
|
+
*/
|
|
2
7
|
export interface CacheEntry<T> {
|
|
8
|
+
/**
|
|
9
|
+
* @en The cached data payload.
|
|
10
|
+
* @ru Сохраненные данные.
|
|
11
|
+
*/
|
|
3
12
|
data: T;
|
|
13
|
+
/**
|
|
14
|
+
* @en HTTP ETag header value for conditional requests.
|
|
15
|
+
* @ru Значение заголовка HTTP ETag для условных запросов.
|
|
16
|
+
*/
|
|
4
17
|
etag?: string;
|
|
18
|
+
/**
|
|
19
|
+
* @en HTTP Last-Modified header value for conditional requests.
|
|
20
|
+
* @ru Значение заголовка HTTP Last-Modified для условных запросов.
|
|
21
|
+
*/
|
|
5
22
|
lastModified?: string;
|
|
6
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* @en Configuration options for the CacheManager.
|
|
26
|
+
* @ru Конфигурационные опции для CacheManager.
|
|
27
|
+
*/
|
|
7
28
|
export interface CacheManagerOptions {
|
|
8
29
|
/**
|
|
9
|
-
* @
|
|
10
|
-
* @
|
|
30
|
+
* @en Enable cache functionality.
|
|
31
|
+
* @ru Включить кэш.
|
|
11
32
|
*/
|
|
12
33
|
enabled?: boolean;
|
|
13
34
|
/**
|
|
14
|
-
* @
|
|
15
|
-
* @
|
|
35
|
+
* @en Cache time-to-live in milliseconds.
|
|
36
|
+
* @ru Время жизни кэша (мс).
|
|
16
37
|
*/
|
|
17
38
|
ttl?: number;
|
|
18
39
|
/**
|
|
19
|
-
* @
|
|
20
|
-
* @
|
|
40
|
+
* @en Maximum number of entries in the cache.
|
|
41
|
+
* @ru Максимальный размер кэша.
|
|
21
42
|
*/
|
|
22
43
|
maxSize?: number;
|
|
23
44
|
/**
|
|
24
|
-
* @
|
|
25
|
-
* @
|
|
45
|
+
* @en HTTP methods allowed to be cached.
|
|
46
|
+
* @ru HTTP методы, которые можно кэшировать.
|
|
26
47
|
*/
|
|
27
48
|
methods?: readonly Method[];
|
|
49
|
+
/**
|
|
50
|
+
* @en Update the expiration time when an entry is accessed.
|
|
51
|
+
* @ru Обновлять время истечения при доступе к записи.
|
|
52
|
+
*/
|
|
53
|
+
updateAgeOnGet?: boolean;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* @en A simplified response object used for efficient cache storage.
|
|
57
|
+
* @ru Упрощенный объект ответа, используемый для эффективного хранения в кэше.
|
|
58
|
+
*/
|
|
59
|
+
export interface LightweightResponse<T = unknown> {
|
|
60
|
+
/**
|
|
61
|
+
* @en The response body content.
|
|
62
|
+
* @ru Содержимое тела ответа.
|
|
63
|
+
*/
|
|
64
|
+
body: T;
|
|
65
|
+
/**
|
|
66
|
+
* @en The HTTP status code.
|
|
67
|
+
* @ru HTTP-код статуса.
|
|
68
|
+
*/
|
|
69
|
+
status: number;
|
|
70
|
+
/**
|
|
71
|
+
* @en The response headers.
|
|
72
|
+
* @ru Заголовки ответа.
|
|
73
|
+
*/
|
|
74
|
+
headers: Record<string, string | string[]>;
|
|
75
|
+
/**
|
|
76
|
+
* @en The final URL of the response.
|
|
77
|
+
* @ru Финальный URL ответа.
|
|
78
|
+
*/
|
|
79
|
+
url: string;
|
|
28
80
|
}
|
|
29
81
|
//# sourceMappingURL=cache.d.ts.map
|
package/types/cache.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/types/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/types/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC;;;;GAIG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B;;;OAGG;IACH,IAAI,EAAE,CAAC,CAAC;IAER;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAE5B;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB,CAAC,CAAC,GAAG,OAAO;IAC9C;;;OAGG;IACH,IAAI,EAAE,CAAC,CAAC;IAER;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAE3C;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;CACb"}
|
package/utils/CacheManager.d.ts
CHANGED
|
@@ -1,78 +1,71 @@
|
|
|
1
1
|
import type { CacheEntry, CacheManagerOptions } from "../types/cache.ts";
|
|
2
2
|
/**
|
|
3
|
-
* @
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* @en High-performance inline in-memory cache with no external dependencies.
|
|
4
|
+
* Uses native Map and lazy invalidation to ensure maximum RPS.
|
|
5
|
+
* @ru Высокопроизводительный инлайновый in-memory кэш без внешних зависимостей.
|
|
6
|
+
* Использует нативный Map и ленивую инвалидацию для обеспечения максимального RPS.
|
|
6
7
|
*
|
|
7
|
-
* @
|
|
8
|
-
* Поддерживает TTL, хранение метаданных (etag, lastModified) и быстрый доступ по ключу.
|
|
8
|
+
* @template T - Type of the data stored in the cache. Defaults to unknown.
|
|
9
9
|
*/
|
|
10
|
-
export declare class CacheManager {
|
|
11
|
-
private readonly
|
|
10
|
+
export declare class CacheManager<T = unknown> {
|
|
11
|
+
private readonly storage;
|
|
12
|
+
private readonly maxSize;
|
|
13
|
+
private readonly ttl;
|
|
14
|
+
private readonly updateAgeOnGet;
|
|
12
15
|
constructor(options?: CacheManagerOptions);
|
|
13
16
|
/**
|
|
14
|
-
* @en Retrieves
|
|
17
|
+
* @en Retrieves a value from the cache by key.
|
|
15
18
|
* @ru Получает значение из кэша по ключу.
|
|
16
|
-
*
|
|
17
|
-
* @
|
|
18
|
-
* @param key Cache key
|
|
19
|
-
* @returns Cached value or undefined if not found
|
|
19
|
+
* @param key - The cache key.
|
|
20
|
+
* @returns The cached value or undefined if not found or expired.
|
|
20
21
|
*/
|
|
21
|
-
get
|
|
22
|
+
get(key: string): T | undefined;
|
|
22
23
|
/**
|
|
23
|
-
* @en Stores value in cache.
|
|
24
|
+
* @en Stores a value in the cache.
|
|
24
25
|
* @ru Сохраняет значение в кэш.
|
|
25
|
-
*
|
|
26
|
-
* @
|
|
27
|
-
* @param key Cache key
|
|
28
|
-
* @param value Value to store
|
|
26
|
+
* @param key - The cache key.
|
|
27
|
+
* @param value - The data to store.
|
|
29
28
|
*/
|
|
30
|
-
set
|
|
29
|
+
set(key: string, value: T): void;
|
|
31
30
|
/**
|
|
32
|
-
* @en Retrieves
|
|
31
|
+
* @en Retrieves a cache entry along with its metadata (etag, lastModified).
|
|
33
32
|
* @ru Получает запись кэша вместе с метаданными (etag, lastModified).
|
|
34
|
-
*
|
|
35
|
-
* @
|
|
36
|
-
* @param key Cache key
|
|
37
|
-
* @returns Cached entry with metadata or undefined
|
|
33
|
+
* @param key - The cache key.
|
|
34
|
+
* @returns The cache entry with metadata or undefined if not found or expired.
|
|
38
35
|
*/
|
|
39
|
-
getWithMetadata
|
|
36
|
+
getWithMetadata(key: string): CacheEntry<T> | undefined;
|
|
40
37
|
/**
|
|
41
|
-
* @en Stores value with
|
|
42
|
-
* @ru Сохраняет значение с дополнительными HTTP
|
|
43
|
-
*
|
|
44
|
-
* @
|
|
45
|
-
* @param
|
|
46
|
-
* @param data Value to store
|
|
47
|
-
* @param meta Optional HTTP metadata
|
|
38
|
+
* @en Stores a value with additional HTTP metadata.
|
|
39
|
+
* @ru Сохраняет значение с дополнительными HTTP метаданными.
|
|
40
|
+
* @param key - The cache key.
|
|
41
|
+
* @param data - The response data to store.
|
|
42
|
+
* @param meta - Optional HTTP metadata (etag, lastModified).
|
|
48
43
|
*/
|
|
49
|
-
setWithMetadata
|
|
44
|
+
setWithMetadata(key: string, data: T, meta?: {
|
|
50
45
|
etag?: string;
|
|
51
46
|
lastModified?: string;
|
|
52
47
|
}): void;
|
|
53
48
|
/**
|
|
54
|
-
* @en Checks
|
|
55
|
-
* @ru Проверяет наличие ключа в
|
|
56
|
-
*
|
|
57
|
-
* @
|
|
58
|
-
* @returns true if exists, otherwise false
|
|
49
|
+
* @en Checks for the existence of a key in the cache without updating its TTL.
|
|
50
|
+
* @ru Проверяет наличие ключа в кэше без обновления его времени жизни.
|
|
51
|
+
* @param key - The cache key.
|
|
52
|
+
* @returns True if the key exists and is not expired.
|
|
59
53
|
*/
|
|
60
54
|
has(key: string): boolean;
|
|
61
55
|
/**
|
|
62
|
-
* @en
|
|
56
|
+
* @en Removes a value from the cache by key.
|
|
63
57
|
* @ru Удаляет значение из кэша по ключу.
|
|
64
|
-
*
|
|
65
|
-
* @
|
|
66
|
-
* @returns true if value was removed
|
|
58
|
+
* @param key - The cache key.
|
|
59
|
+
* @returns True if the element was removed, false otherwise.
|
|
67
60
|
*/
|
|
68
61
|
delete(key: string): boolean;
|
|
69
62
|
/**
|
|
70
|
-
* @en Clears entire cache.
|
|
63
|
+
* @en Clears the entire cache.
|
|
71
64
|
* @ru Очищает весь кэш.
|
|
72
65
|
*/
|
|
73
66
|
clear(): void;
|
|
74
67
|
/**
|
|
75
|
-
* @en Returns current cache
|
|
68
|
+
* @en Returns the current number of items in the cache.
|
|
76
69
|
* @ru Возвращает текущий размер кэша.
|
|
77
70
|
*/
|
|
78
71
|
get size(): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CacheManager.d.ts","sourceRoot":"","sources":["../../src/utils/CacheManager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CacheManager.d.ts","sourceRoot":"","sources":["../../src/utils/CacheManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAczE;;;;;;;GAOG;AACH,qBAAa,YAAY,CAAC,CAAC,GAAG,OAAO;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4C;IACpE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;gBAE7B,OAAO,CAAC,EAAE,mBAAmB;IAMzC;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAoB/B;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAgBhC;;;;;OAKG;IACH,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS;IAuBvD;;;;;;OAMG;IACH,eAAe,CACb,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,CAAC,EACP,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9C,IAAI;IAoBP;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAWzB;;;;;OAKG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B;;;OAGG;IACH,KAAK,IAAI,IAAI;IAIb;;;OAGG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
package/utils/CacheManager.js
CHANGED
|
@@ -1,106 +1,154 @@
|
|
|
1
|
-
import { LRUCache } from "lru-cache";
|
|
2
1
|
/**
|
|
3
|
-
* @
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* @en High-performance inline in-memory cache with no external dependencies.
|
|
3
|
+
* Uses native Map and lazy invalidation to ensure maximum RPS.
|
|
4
|
+
* @ru Высокопроизводительный инлайновый in-memory кэш без внешних зависимостей.
|
|
5
|
+
* Использует нативный Map и ленивую инвалидацию для обеспечения максимального RPS.
|
|
6
6
|
*
|
|
7
|
-
* @
|
|
8
|
-
* Поддерживает TTL, хранение метаданных (etag, lastModified) и быстрый доступ по ключу.
|
|
7
|
+
* @template T - Type of the data stored in the cache. Defaults to unknown.
|
|
9
8
|
*/
|
|
10
9
|
export class CacheManager {
|
|
11
|
-
|
|
10
|
+
storage = new Map();
|
|
11
|
+
maxSize;
|
|
12
|
+
ttl;
|
|
13
|
+
updateAgeOnGet;
|
|
12
14
|
constructor(options) {
|
|
13
|
-
this.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
updateAgeOnGet: true,
|
|
17
|
-
});
|
|
15
|
+
this.maxSize = options?.maxSize ?? 500;
|
|
16
|
+
this.ttl = options?.ttl ?? 300_000;
|
|
17
|
+
this.updateAgeOnGet = options?.updateAgeOnGet ?? true;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
* @en Retrieves
|
|
20
|
+
* @en Retrieves a value from the cache by key.
|
|
21
21
|
* @ru Получает значение из кэша по ключу.
|
|
22
|
-
*
|
|
23
|
-
* @
|
|
24
|
-
* @param key Cache key
|
|
25
|
-
* @returns Cached value or undefined if not found
|
|
22
|
+
* @param key - The cache key.
|
|
23
|
+
* @returns The cached value or undefined if not found or expired.
|
|
26
24
|
*/
|
|
27
25
|
get(key) {
|
|
28
|
-
|
|
26
|
+
const entry = this.storage.get(key);
|
|
27
|
+
if (!entry)
|
|
28
|
+
return undefined;
|
|
29
|
+
const now = Date.now();
|
|
30
|
+
if (now > entry.expiresAt) {
|
|
31
|
+
this.storage.delete(key);
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
if (this.updateAgeOnGet) {
|
|
35
|
+
entry.expiresAt = now + this.ttl;
|
|
36
|
+
// Move to end for LRU
|
|
37
|
+
this.storage.delete(key);
|
|
38
|
+
this.storage.set(key, entry);
|
|
39
|
+
}
|
|
40
|
+
return entry.data;
|
|
29
41
|
}
|
|
30
42
|
/**
|
|
31
|
-
* @en Stores value in cache.
|
|
43
|
+
* @en Stores a value in the cache.
|
|
32
44
|
* @ru Сохраняет значение в кэш.
|
|
33
|
-
*
|
|
34
|
-
* @
|
|
35
|
-
* @param key Cache key
|
|
36
|
-
* @param value Value to store
|
|
45
|
+
* @param key - The cache key.
|
|
46
|
+
* @param value - The data to store.
|
|
37
47
|
*/
|
|
38
48
|
set(key, value) {
|
|
39
|
-
|
|
49
|
+
const now = Date.now();
|
|
50
|
+
if (this.storage.has(key)) {
|
|
51
|
+
this.storage.delete(key);
|
|
52
|
+
}
|
|
53
|
+
else if (this.storage.size >= this.maxSize) {
|
|
54
|
+
const oldestKey = this.storage.keys().next().value;
|
|
55
|
+
if (oldestKey !== undefined)
|
|
56
|
+
this.storage.delete(oldestKey);
|
|
57
|
+
}
|
|
58
|
+
this.storage.set(key, {
|
|
40
59
|
data: value,
|
|
60
|
+
expiresAt: now + this.ttl,
|
|
41
61
|
});
|
|
42
62
|
}
|
|
43
63
|
/**
|
|
44
|
-
* @en Retrieves
|
|
64
|
+
* @en Retrieves a cache entry along with its metadata (etag, lastModified).
|
|
45
65
|
* @ru Получает запись кэша вместе с метаданными (etag, lastModified).
|
|
46
|
-
*
|
|
47
|
-
* @
|
|
48
|
-
* @param key Cache key
|
|
49
|
-
* @returns Cached entry with metadata or undefined
|
|
66
|
+
* @param key - The cache key.
|
|
67
|
+
* @returns The cache entry with metadata or undefined if not found or expired.
|
|
50
68
|
*/
|
|
51
69
|
getWithMetadata(key) {
|
|
52
|
-
const entry = this.
|
|
53
|
-
|
|
70
|
+
const entry = this.storage.get(key);
|
|
71
|
+
if (!entry)
|
|
72
|
+
return undefined;
|
|
73
|
+
const now = Date.now();
|
|
74
|
+
if (now > entry.expiresAt) {
|
|
75
|
+
this.storage.delete(key);
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
if (this.updateAgeOnGet) {
|
|
79
|
+
entry.expiresAt = now + this.ttl;
|
|
80
|
+
this.storage.delete(key);
|
|
81
|
+
this.storage.set(key, entry);
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
data: entry.data,
|
|
85
|
+
etag: entry.etag,
|
|
86
|
+
lastModified: entry.lastModified,
|
|
87
|
+
};
|
|
54
88
|
}
|
|
55
89
|
/**
|
|
56
|
-
* @en Stores value with
|
|
57
|
-
* @ru Сохраняет значение с дополнительными HTTP
|
|
58
|
-
*
|
|
59
|
-
* @
|
|
60
|
-
* @param
|
|
61
|
-
* @param data Value to store
|
|
62
|
-
* @param meta Optional HTTP metadata
|
|
90
|
+
* @en Stores a value with additional HTTP metadata.
|
|
91
|
+
* @ru Сохраняет значение с дополнительными HTTP метаданными.
|
|
92
|
+
* @param key - The cache key.
|
|
93
|
+
* @param data - The response data to store.
|
|
94
|
+
* @param meta - Optional HTTP metadata (etag, lastModified).
|
|
63
95
|
*/
|
|
64
96
|
setWithMetadata(key, data, meta) {
|
|
65
|
-
|
|
97
|
+
const now = Date.now();
|
|
98
|
+
if (this.storage.has(key)) {
|
|
99
|
+
this.storage.delete(key);
|
|
100
|
+
}
|
|
101
|
+
else if (this.storage.size >= this.maxSize) {
|
|
102
|
+
const oldestKey = this.storage.keys().next().value;
|
|
103
|
+
if (oldestKey !== undefined) {
|
|
104
|
+
this.storage.delete(oldestKey);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
this.storage.set(key, {
|
|
66
108
|
data,
|
|
67
109
|
etag: meta?.etag,
|
|
68
110
|
lastModified: meta?.lastModified,
|
|
111
|
+
expiresAt: now + this.ttl,
|
|
69
112
|
});
|
|
70
113
|
}
|
|
71
114
|
/**
|
|
72
|
-
* @en Checks
|
|
73
|
-
* @ru Проверяет наличие ключа в
|
|
74
|
-
*
|
|
75
|
-
* @
|
|
76
|
-
* @returns true if exists, otherwise false
|
|
115
|
+
* @en Checks for the existence of a key in the cache without updating its TTL.
|
|
116
|
+
* @ru Проверяет наличие ключа в кэше без обновления его времени жизни.
|
|
117
|
+
* @param key - The cache key.
|
|
118
|
+
* @returns True if the key exists and is not expired.
|
|
77
119
|
*/
|
|
78
120
|
has(key) {
|
|
79
|
-
|
|
121
|
+
const entry = this.storage.get(key);
|
|
122
|
+
if (!entry)
|
|
123
|
+
return false;
|
|
124
|
+
if (Date.now() > entry.expiresAt) {
|
|
125
|
+
this.storage.delete(key);
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
return true;
|
|
80
129
|
}
|
|
81
130
|
/**
|
|
82
|
-
* @en
|
|
131
|
+
* @en Removes a value from the cache by key.
|
|
83
132
|
* @ru Удаляет значение из кэша по ключу.
|
|
84
|
-
*
|
|
85
|
-
* @
|
|
86
|
-
* @returns true if value was removed
|
|
133
|
+
* @param key - The cache key.
|
|
134
|
+
* @returns True if the element was removed, false otherwise.
|
|
87
135
|
*/
|
|
88
136
|
delete(key) {
|
|
89
|
-
return this.
|
|
137
|
+
return this.storage.delete(key);
|
|
90
138
|
}
|
|
91
139
|
/**
|
|
92
|
-
* @en Clears entire cache.
|
|
140
|
+
* @en Clears the entire cache.
|
|
93
141
|
* @ru Очищает весь кэш.
|
|
94
142
|
*/
|
|
95
143
|
clear() {
|
|
96
|
-
this.
|
|
144
|
+
this.storage.clear();
|
|
97
145
|
}
|
|
98
146
|
/**
|
|
99
|
-
* @en Returns current cache
|
|
147
|
+
* @en Returns the current number of items in the cache.
|
|
100
148
|
* @ru Возвращает текущий размер кэша.
|
|
101
149
|
*/
|
|
102
150
|
get size() {
|
|
103
|
-
return this.
|
|
151
|
+
return this.storage.size;
|
|
104
152
|
}
|
|
105
153
|
}
|
|
106
154
|
//# sourceMappingURL=CacheManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CacheManager.js","sourceRoot":"","sources":["../../src/utils/CacheManager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CacheManager.js","sourceRoot":"","sources":["../../src/utils/CacheManager.ts"],"names":[],"mappings":"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"}
|