koatty_cacheable 3.0.4 → 3.0.6

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/index.mjs CHANGED
@@ -1,377 +1,269 @@
1
+ import { Helper } from 'koatty_lib';
2
+ import { DefaultLogger } from 'koatty_logger';
3
+ import { CacheStore } from 'koatty_store';
4
+ import { IOCContainer } from 'koatty_container';
5
+
1
6
  /*!
2
7
  * @Author: richen
3
- * @Date: 2026-02-04 10:58:15
8
+ * @Date: 2026-02-11 03:41:57
4
9
  * @License: BSD (3-Clause)
5
10
  * @Copyright (c) - <richenlin(at)gmail.com>
6
11
  * @HomePage: https://koatty.org/
7
12
  */
8
- import { Helper } from 'koatty_lib';
9
- import { DefaultLogger } from 'koatty_logger';
10
- import { CacheStore } from 'koatty_store';
11
- import { IOCContainer } from 'koatty_container';
12
-
13
- /*
14
- * @Description:
15
- * @Usage:
16
- * @Author: richen
17
- * @Date: 2024-11-07 16:00:02
18
- * @LastEditTime: 2024-11-07 16:00:05
19
- * @License: BSD (3-Clause)
20
- * @Copyright (c): <richenlin(at)gmail.com>
21
- */
22
- // storeCache
23
- const storeCache = {
24
- store: null
13
+ var __defProp = Object.defineProperty;
14
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
15
+ var storeCache = {
16
+ store: null
25
17
  };
26
- // Promise to track initialization in progress
27
- let initPromise = null;
28
- /**
29
- * get instances of storeCache
30
- *
31
- * @export
32
- * @param {StoreOptions} options
33
- * @returns {*} {CacheStore}
34
- */
18
+ var initPromise = null;
35
19
  async function GetCacheStore(options) {
36
- // Return existing store if available
37
- if (storeCache.store && storeCache.store.getConnection) {
38
- return storeCache.store;
39
- }
40
- // If initialization is in progress, wait for it
41
- if (initPromise) {
42
- return initPromise;
43
- }
44
- if (Helper.isEmpty(options)) {
45
- if (!storeCache.store) {
46
- DefaultLogger.Warn(`CacheStore not initialized. Please call KoattyCached() first with proper options in your application startup.`);
47
- }
48
- return storeCache.store || null;
49
- }
50
- // Start initialization and track it
51
- initPromise = (async () => {
52
- try {
53
- storeCache.store = CacheStore.getInstance(options);
54
- if (!Helper.isFunction(storeCache.store.getConnection)) {
55
- throw Error(`CacheStore connection failed. `);
56
- }
57
- await storeCache.store.client.getConnection();
58
- return storeCache.store;
59
- }
60
- finally {
61
- // Clear init promise after completion
62
- initPromise = null;
63
- }
64
- })();
20
+ if (storeCache.store && storeCache.store.getConnection) {
21
+ return storeCache.store;
22
+ }
23
+ if (initPromise) {
65
24
  return initPromise;
66
- }
67
- /**
68
- * Close cache store connection for cleanup (mainly for testing)
69
- */
70
- async function CloseCacheStore() {
71
- if (storeCache.store) {
72
- try {
73
- if (storeCache.store.client) {
74
- const client = storeCache.store.client;
75
- if (typeof client.quit === 'function') {
76
- await client.quit();
77
- }
78
- else if (typeof client.close === 'function') {
79
- await client.close();
80
- }
81
- }
82
- }
83
- catch {
84
- // Ignore cleanup errors
85
- }
25
+ }
26
+ if (Helper.isEmpty(options)) {
27
+ if (!storeCache.store) {
28
+ DefaultLogger.Warn(`CacheStore not initialized. Please call KoattyCached() first with proper options in your application startup.`);
86
29
  }
87
- // Clear the CacheStore singleton instance
30
+ return storeCache.store || null;
31
+ }
32
+ initPromise = (async () => {
88
33
  try {
89
- await CacheStore.clearAllInstances();
90
- }
91
- catch {
92
- // Ignore cleanup errors
34
+ storeCache.store = CacheStore.getInstance(options);
35
+ if (!Helper.isFunction(storeCache.store.getConnection)) {
36
+ throw Error(`CacheStore connection failed. `);
37
+ }
38
+ await storeCache.store.client.getConnection();
39
+ return storeCache.store;
40
+ } finally {
41
+ initPromise = null;
93
42
  }
94
- // Always clear the cache
95
- storeCache.store = null;
96
- initPromise = null;
43
+ })();
44
+ return initPromise;
97
45
  }
98
-
99
- /* eslint-disable @typescript-eslint/no-unused-vars */
100
- /*
101
- * @Description:
102
- * @Usage:
103
- * @Author: richen
104
- * @Date: 2024-11-07 13:54:24
105
- * @LastEditTime: 2024-11-07 15:25:36
106
- * @License: BSD (3-Clause)
107
- * @Copyright (c): <richenlin(at)gmail.com>
108
- */
109
- const longKey = 128;
110
- /**
111
- * Extract parameter names from function signature
112
- * @param func The function to extract parameters from
113
- * @returns Array of parameter names
114
- */
115
- function getArgs(func) {
46
+ __name(GetCacheStore, "GetCacheStore");
47
+ async function CloseCacheStore() {
48
+ if (storeCache.store) {
116
49
  try {
117
- // Match function parameters in parentheses
118
- const args = func.toString().match(/.*?\(([^)]*)\)/);
119
- if (args && args.length > 1) {
120
- // Split parameters into array and clean them
121
- return args[1].split(",").map(function (a) {
122
- // Remove multi-line comments /* ... */ and single-line comments //
123
- const param = a.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "").trim();
124
- // Extract parameter name (before : or = or end of string)
125
- const match = param.match(/^(\w+)/);
126
- return match ? match[1] : "";
127
- }).filter(function (ae) {
128
- // Filter out empty strings
129
- return ae;
130
- });
50
+ if (storeCache.store.client) {
51
+ const client = storeCache.store.client;
52
+ if (typeof client.quit === "function") {
53
+ await client.quit();
54
+ } else if (typeof client.close === "function") {
55
+ await client.close();
131
56
  }
132
- return [];
57
+ }
58
+ } catch {
133
59
  }
134
- catch (error) {
135
- // Return empty array if parsing fails
136
- return [];
60
+ }
61
+ try {
62
+ await CacheStore.clearAllInstances();
63
+ } catch {
64
+ }
65
+ storeCache.store = null;
66
+ initPromise = null;
67
+ }
68
+ __name(CloseCacheStore, "CloseCacheStore");
69
+ var longKey = 128;
70
+ function getArgs(func) {
71
+ try {
72
+ const args = func.toString().match(/.*?\(([^)]*)\)/);
73
+ if (args && args.length > 1) {
74
+ return args[1].split(",").map(function(a) {
75
+ const param = a.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "").trim();
76
+ const match = param.match(/^(\w+)/);
77
+ return match ? match[1] : "";
78
+ }).filter(function(ae) {
79
+ return ae;
80
+ });
137
81
  }
82
+ return [];
83
+ } catch (error) {
84
+ return [];
85
+ }
138
86
  }
139
- /**
140
- * Get parameter indexes based on parameter names
141
- * @param funcParams Function parameter names
142
- * @param params Target parameter names to find indexes for
143
- * @returns Array of parameter indexes (-1 if not found)
144
- */
87
+ __name(getArgs, "getArgs");
145
88
  function getParamIndex(funcParams, params) {
146
- return params.map(param => funcParams.indexOf(param));
89
+ return params.map((param) => funcParams.indexOf(param));
147
90
  }
148
- /**
149
- * Generate cache key based on cache name and parameters
150
- * @param cacheName base cache name
151
- * @param paramIndexes parameter indexes
152
- * @param paramNames parameter names
153
- * @param props method arguments
154
- * @returns generated cache key
155
- */
91
+ __name(getParamIndex, "getParamIndex");
156
92
  function generateCacheKey(cacheName, paramIndexes, paramNames, props) {
157
- let key = cacheName;
158
- for (let i = 0; i < paramIndexes.length; i++) {
159
- const paramIndex = paramIndexes[i];
160
- if (paramIndex >= 0 && props[paramIndex] !== undefined) {
161
- key += `:${paramNames[i]}:${Helper.toString(props[paramIndex])}`;
162
- }
93
+ let key = cacheName;
94
+ for (let i = 0; i < paramIndexes.length; i++) {
95
+ const paramIndex = paramIndexes[i];
96
+ if (paramIndex >= 0 && props[paramIndex] !== void 0) {
97
+ key += `:${paramNames[i]}:${Helper.toString(props[paramIndex])}`;
163
98
  }
164
- return key.length > longKey ? Helper.murmurHash(key) : key;
99
+ }
100
+ return key.length > longKey ? Helper.murmurHash(key) : key;
165
101
  }
166
- /**
167
- * Create a delay promise
168
- * @param ms Delay time in milliseconds
169
- * @returns Promise that resolves after the specified delay
170
- */
102
+ __name(generateCacheKey, "generateCacheKey");
171
103
  function delay(ms) {
172
- return new Promise(resolve => setTimeout(resolve, ms));
104
+ return new Promise((resolve) => setTimeout(resolve, ms));
173
105
  }
174
- /**
175
- * Execute a function after a specified delay
176
- * @param fn Function to execute
177
- * @param ms Delay time in milliseconds
178
- * @returns Promise that resolves with the function result
179
- */
106
+ __name(delay, "delay");
180
107
  async function asyncDelayedExecution(fn, ms) {
181
- await delay(ms);
182
- return fn();
108
+ await delay(ms);
109
+ return fn();
183
110
  }
111
+ __name(asyncDelayedExecution, "asyncDelayedExecution");
184
112
 
185
- /*
186
- * @Author: richen
187
- * @Date: 2020-07-06 19:53:43
188
- * @LastEditTime: 2024-11-07 15:53:46
189
- * @Description:
190
- * @Copyright (c) - <richenlin(at)gmail.com>
191
- */
192
- /**
193
- * Decorate this method to support caching.
194
- * The cache method returns a value to ensure that the next time
195
- * the method is executed with the same parameters, the results can be obtained
196
- * directly from the cache without the need to execute the method again.
197
- * CacheStore server config defined in db.ts.
198
- *
199
- * @export
200
- * @param {string} cacheName cache name
201
- * @param {CacheAbleOpt} [opt] cache options
202
- * e.g:
203
- * {
204
- * params: ["id"],
205
- * timeout: 30
206
- * }
207
- * Use the 'id' parameters of the method as cache subkeys, the cache expiration time 30s
208
- * @returns {MethodDecorator}
209
- */
113
+ // src/cache.ts
210
114
  function CacheAble(cacheName, opt = {
211
- params: [],
212
- timeout: 300,
115
+ params: [],
116
+ timeout: 300
213
117
  }) {
214
- return (target, methodName, descriptor) => {
215
- const componentType = IOCContainer.getType(target);
216
- if (!["SERVICE", "COMPONENT"].includes(componentType)) {
217
- throw Error("This decorator only used in the service、component class.");
218
- }
219
- const { value, configurable, enumerable } = descriptor;
220
- const mergedOpt = { ...{ params: [], timeout: 300 }, ...opt };
221
- // Get the parameter list of the method
222
- const funcParams = getArgs(target[methodName]);
223
- // Get the defined parameter location
224
- const paramIndexes = getParamIndex(funcParams, mergedOpt.params || []);
225
- // Validate parameters
226
- const invalidParams = [];
227
- (mergedOpt.params || []).forEach((param, index) => {
228
- if (paramIndexes[index] === -1) {
229
- invalidParams.push(param);
230
- }
118
+ return (target, methodName, descriptor) => {
119
+ const componentType = IOCContainer.getType(target);
120
+ if (![
121
+ "SERVICE",
122
+ "COMPONENT"
123
+ ].includes(componentType)) {
124
+ throw Error("This decorator only used in the service\u3001component class.");
125
+ }
126
+ const { value, configurable, enumerable } = descriptor;
127
+ const mergedOpt = {
128
+ ...{
129
+ params: [],
130
+ timeout: 300
131
+ },
132
+ ...opt
133
+ };
134
+ const funcParams = getArgs(target[methodName]);
135
+ const paramIndexes = getParamIndex(funcParams, mergedOpt.params || []);
136
+ const invalidParams = [];
137
+ (mergedOpt.params || []).forEach((param, index) => {
138
+ if (paramIndexes[index] === -1) {
139
+ invalidParams.push(param);
140
+ }
141
+ });
142
+ if (invalidParams.length > 0) {
143
+ DefaultLogger.Warn(`CacheAble: Parameter(s) [${invalidParams.join(", ")}] not found in method ${String(methodName)}. These parameters will be ignored.`);
144
+ }
145
+ descriptor = {
146
+ configurable,
147
+ enumerable,
148
+ writable: true,
149
+ async value(...props) {
150
+ const store = await GetCacheStore().catch((e) => {
151
+ DefaultLogger.error("Get cache store instance failed." + e.message);
152
+ return null;
231
153
  });
232
- if (invalidParams.length > 0) {
233
- DefaultLogger.Warn(`CacheAble: Parameter(s) [${invalidParams.join(", ")}] not found in method ${String(methodName)}. These parameters will be ignored.`);
234
- }
235
- descriptor = {
236
- configurable,
237
- enumerable,
238
- writable: true,
239
- async value(...props) {
240
- const store = await GetCacheStore().catch((e) => {
241
- DefaultLogger.error("Get cache store instance failed." + e.message);
242
- return null;
243
- });
244
- if (store) {
245
- const key = generateCacheKey(cacheName, paramIndexes, mergedOpt.params, props);
246
- const res = await store.get(key).catch((e) => {
247
- DefaultLogger.error("Cache get error:" + e.message);
248
- });
249
- if (!Helper.isEmpty(res)) {
250
- try {
251
- return JSON.parse(res);
252
- }
253
- catch (e) {
254
- const error = e;
255
- DefaultLogger.error("Cache JSON parse error:" + error.message);
256
- // 如果解析失败,删除损坏的缓存,重新执行方法
257
- store.del(key).catch((err) => {
258
- DefaultLogger.error("Cache del error after parse failure:" + err.message);
259
- });
260
- }
261
- }
262
- const result = await value.apply(this, props);
263
- // async refresh store
264
- store.set(key, Helper.isJSONObj(result) ? JSON.stringify(result) : result, mergedOpt.timeout).catch((e) => {
265
- DefaultLogger.error("Cache set error:" + e.message);
266
- });
267
- return result;
268
- }
269
- else {
270
- // tslint:disable-next-line: no-invalid-this
271
- return value.apply(this, props);
272
- }
154
+ if (store) {
155
+ const key = generateCacheKey(cacheName, paramIndexes, mergedOpt.params, props);
156
+ const res = await store.get(key).catch((e) => {
157
+ DefaultLogger.error("Cache get error:" + e.message);
158
+ });
159
+ if (!Helper.isEmpty(res)) {
160
+ try {
161
+ return JSON.parse(res);
162
+ } catch (e) {
163
+ const error = e;
164
+ DefaultLogger.error("Cache JSON parse error:" + error.message);
165
+ store.del(key).catch((err) => {
166
+ DefaultLogger.error("Cache del error after parse failure:" + err.message);
167
+ });
273
168
  }
274
- };
275
- return descriptor;
169
+ }
170
+ const result = await value.apply(this, props);
171
+ store.set(key, Helper.isJSONObj(result) ? JSON.stringify(result) : result, mergedOpt.timeout).catch((e) => {
172
+ DefaultLogger.error("Cache set error:" + e.message);
173
+ });
174
+ return result;
175
+ } else {
176
+ return value.apply(this, props);
177
+ }
178
+ }
276
179
  };
180
+ return descriptor;
181
+ };
277
182
  }
278
- /**
279
- * Decorating the execution of this method will trigger a cache clear operation.
280
- * CacheStore server config defined in db.ts.
281
- *
282
- * @export
283
- * @param {string} cacheName cacheName cache name
284
- * @param {CacheEvictOpt} [opt] cache options
285
- * e.g:
286
- * {
287
- * params: ["id"],
288
- * delayedDoubleDeletion: true
289
- * }
290
- * Use the 'id' parameters of the method as cache subkeys,
291
- * and clear the cache after the method executed
292
- * @returns
293
- */
183
+ __name(CacheAble, "CacheAble");
294
184
  function CacheEvict(cacheName, opt = {
295
- delayedDoubleDeletion: true,
185
+ delayedDoubleDeletion: true
296
186
  }) {
297
- return (target, methodName, descriptor) => {
298
- const componentType = IOCContainer.getType(target);
299
- if (!["SERVICE", "COMPONENT"].includes(componentType)) {
300
- throw Error("This decorator only used in the service、component class.");
301
- }
302
- const { value, configurable, enumerable } = descriptor;
303
- opt = { ...{ delayedDoubleDeletion: true, }, ...opt };
304
- // Get the parameter list of the method
305
- const funcParams = getArgs(target[methodName]);
306
- // Get the defined parameter location
307
- const paramIndexes = getParamIndex(funcParams, opt.params || []);
308
- // Validate parameters
309
- const invalidParams = [];
310
- (opt.params || []).forEach((param, index) => {
311
- if (paramIndexes[index] === -1) {
312
- invalidParams.push(param);
313
- }
187
+ return (target, methodName, descriptor) => {
188
+ const componentType = IOCContainer.getType(target);
189
+ if (![
190
+ "SERVICE",
191
+ "COMPONENT"
192
+ ].includes(componentType)) {
193
+ throw Error("This decorator only used in the service\u3001component class.");
194
+ }
195
+ const { value, configurable, enumerable } = descriptor;
196
+ opt = {
197
+ ...{
198
+ delayedDoubleDeletion: true
199
+ },
200
+ ...opt
201
+ };
202
+ const funcParams = getArgs(target[methodName]);
203
+ const paramIndexes = getParamIndex(funcParams, opt.params || []);
204
+ const invalidParams = [];
205
+ (opt.params || []).forEach((param, index) => {
206
+ if (paramIndexes[index] === -1) {
207
+ invalidParams.push(param);
208
+ }
209
+ });
210
+ if (invalidParams.length > 0) {
211
+ DefaultLogger.Warn(`CacheEvict: Parameter(s) [${invalidParams.join(", ")}] not found in method ${String(methodName)}. These parameters will be ignored.`);
212
+ }
213
+ descriptor = {
214
+ configurable,
215
+ enumerable,
216
+ writable: true,
217
+ async value(...props) {
218
+ const store = await GetCacheStore().catch((e) => {
219
+ DefaultLogger.error("Get cache store instance failed." + e.message);
220
+ return null;
314
221
  });
315
- if (invalidParams.length > 0) {
316
- DefaultLogger.Warn(`CacheEvict: Parameter(s) [${invalidParams.join(", ")}] not found in method ${String(methodName)}. These parameters will be ignored.`);
222
+ if (store) {
223
+ const key = generateCacheKey(cacheName, paramIndexes, opt.params || [], props);
224
+ const result = await value.apply(this, props);
225
+ store.del(key).catch((e) => {
226
+ DefaultLogger.error("Cache delete error:" + e.message);
227
+ });
228
+ if (opt.delayedDoubleDeletion) {
229
+ const delayTime = opt.delayTime || 5e3;
230
+ asyncDelayedExecution(() => {
231
+ store.del(key).catch((e) => {
232
+ DefaultLogger.error("Cache double delete error:" + e.message);
233
+ });
234
+ }, delayTime);
235
+ }
236
+ return result;
237
+ } else {
238
+ return value.apply(this, props);
317
239
  }
318
- descriptor = {
319
- configurable,
320
- enumerable,
321
- writable: true,
322
- async value(...props) {
323
- const store = await GetCacheStore().catch((e) => {
324
- DefaultLogger.error("Get cache store instance failed." + e.message);
325
- return null;
326
- });
327
- if (store) {
328
- const key = generateCacheKey(cacheName, paramIndexes, opt.params || [], props);
329
- const result = await value.apply(this, props);
330
- store.del(key).catch((e) => {
331
- DefaultLogger.error("Cache delete error:" + e.message);
332
- });
333
- if (opt.delayedDoubleDeletion) {
334
- const delayTime = opt.delayTime || 5000;
335
- asyncDelayedExecution(() => {
336
- store.del(key).catch((e) => {
337
- DefaultLogger.error("Cache double delete error:" + e.message);
338
- });
339
- }, delayTime);
340
- }
341
- return result;
342
- }
343
- else {
344
- // If store is not available, execute method directly
345
- return value.apply(this, props);
346
- }
347
- }
348
- };
349
- return descriptor;
240
+ }
350
241
  };
242
+ return descriptor;
243
+ };
351
244
  }
245
+ __name(CacheEvict, "CacheEvict");
352
246
 
353
- /**
354
- * defaultOptions
355
- */
356
- const defaultOptions = {
357
- type: "memory",
358
- db: 0,
359
- timeout: 30
247
+ // src/index.ts
248
+ var defaultOptions = {
249
+ type: "memory",
250
+ db: 0,
251
+ timeout: 30
360
252
  };
361
- /**
362
- * @param options - The options for the cached options
363
- * @param app - The Koatty application instance
364
- */
365
253
  async function KoattyCached(options, app) {
366
- options = { ...defaultOptions, ...options };
367
- app.once("appReady", async function () {
368
- // 初始化缓存存储
369
- await GetCacheStore(options);
370
- });
371
- app.on("appStop", async function () {
372
- // 关闭缓存存储
373
- await CloseCacheStore();
374
- });
254
+ options = {
255
+ ...defaultOptions,
256
+ ...options
257
+ };
258
+ app.once("appReady", async function() {
259
+ await GetCacheStore(options);
260
+ });
261
+ app.on("appStop", async function() {
262
+ await CloseCacheStore();
263
+ });
375
264
  }
265
+ __name(KoattyCached, "KoattyCached");
376
266
 
377
267
  export { CacheAble, CacheEvict, CloseCacheStore, GetCacheStore, KoattyCached };
268
+ //# sourceMappingURL=index.mjs.map
269
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/store.ts","../src/utils.ts","../src/cache.ts","../src/index.ts"],"names":["storeCache","store","initPromise","GetCacheStore","options","getConnection","Helper","isEmpty","logger","Warn","CacheStore","getInstance","isFunction","Error","client","CloseCacheStore","quit","close","clearAllInstances","longKey","getArgs","func","args","toString","match","length","split","map","a","param","replace","trim","filter","ae","error","getParamIndex","funcParams","params","indexOf","generateCacheKey","cacheName","paramIndexes","paramNames","props","key","i","paramIndex","undefined","murmurHash","delay","ms","Promise","resolve","setTimeout","asyncDelayedExecution","fn","CacheAble","opt","timeout","target","methodName","descriptor","componentType","IOCContainer","getType","includes","value","configurable","enumerable","mergedOpt","invalidParams","forEach","index","push","join","String","writable","catch","e","message","res","get","JSON","parse","del","err","result","apply","set","isJSONObj","stringify","CacheEvict","delayedDoubleDeletion","delayTime","defaultOptions","type","db","KoattyCached","app","once","on"],"mappings":"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","file":"index.mjs","sourcesContent":["/*\n * @Description: \n * @Usage: \n * @Author: richen\n * @Date: 2024-11-07 16:00:02\n * @LastEditTime: 2024-11-07 16:00:05\n * @License: BSD (3-Clause)\n * @Copyright (c): <richenlin(at)gmail.com>\n */\nimport { Helper } from \"koatty_lib\";\nimport { DefaultLogger as logger } from \"koatty_logger\";\nimport { CacheStore, StoreOptions } from \"koatty_store\";\n\n/**\n * \n *\n * @interface CacheStoreInterface\n */\ninterface CacheStoreInterface {\n store?: CacheStore;\n}\n\n// storeCache\nconst storeCache: CacheStoreInterface = {\n store: null\n};\n\n// Promise to track initialization in progress\nlet initPromise: Promise<CacheStore> | null = null;\n\n/**\n * get instances of storeCache\n *\n * @export\n * @param {StoreOptions} options\n * @returns {*} {CacheStore}\n */\nexport async function GetCacheStore(options?: StoreOptions): Promise<CacheStore> {\n // Return existing store if available\n if (storeCache.store && storeCache.store.getConnection) {\n return storeCache.store;\n }\n\n // If initialization is in progress, wait for it\n if (initPromise) {\n return initPromise;\n }\n\n if (Helper.isEmpty(options)) {\n if (!storeCache.store) {\n logger.Warn(`CacheStore not initialized. Please call KoattyCached() first with proper options in your application startup.`);\n }\n return storeCache.store || null;\n }\n\n // Start initialization and track it\n initPromise = (async () => {\n try {\n storeCache.store = CacheStore.getInstance(options);\n if (!Helper.isFunction(storeCache.store.getConnection)) {\n throw Error(`CacheStore connection failed. `);\n }\n await storeCache.store.client.getConnection();\n return storeCache.store;\n } finally {\n // Clear init promise after completion\n initPromise = null;\n }\n })();\n\n return initPromise;\n}\n\n/**\n * Close cache store connection for cleanup (mainly for testing)\n */\nexport async function CloseCacheStore(): Promise<void> {\n if (storeCache.store) {\n try {\n if (storeCache.store.client) {\n const client = storeCache.store.client as any;\n if (typeof client.quit === 'function') {\n await client.quit();\n } else if (typeof client.close === 'function') {\n await client.close();\n }\n }\n } catch {\n // Ignore cleanup errors\n }\n }\n \n // Clear the CacheStore singleton instance\n try {\n await CacheStore.clearAllInstances();\n } catch {\n // Ignore cleanup errors\n }\n \n // Always clear the cache\n storeCache.store = null;\n initPromise = null;\n}","/* eslint-disable @typescript-eslint/no-unused-vars */\n/*\n * @Description: \n * @Usage: \n * @Author: richen\n * @Date: 2024-11-07 13:54:24\n * @LastEditTime: 2024-11-07 15:25:36\n * @License: BSD (3-Clause)\n * @Copyright (c): <richenlin(at)gmail.com>\n */\n\nimport { Helper } from \"koatty_lib\";\n\nconst longKey = 128;\n\n/**\n * Extract parameter names from function signature\n * @param func The function to extract parameters from\n * @returns Array of parameter names\n */\nexport function getArgs(func: (...args: any[]) => any): string[] {\n try {\n // Match function parameters in parentheses\n const args = func.toString().match(/.*?\\(([^)]*)\\)/);\n if (args && args.length > 1) {\n // Split parameters into array and clean them\n return args[1].split(\",\").map(function (a) {\n // Remove multi-line comments /* ... */ and single-line comments //\n const param = a.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\").replace(/\\/\\/.*$/gm, \"\").trim();\n // Extract parameter name (before : or = or end of string)\n const match = param.match(/^(\\w+)/);\n return match ? match[1] : \"\";\n }).filter(function (ae) {\n // Filter out empty strings\n return ae;\n });\n }\n return [];\n } catch (error) {\n // Return empty array if parsing fails\n return [];\n }\n}\n\n/**\n * Get parameter indexes based on parameter names\n * @param funcParams Function parameter names\n * @param params Target parameter names to find indexes for\n * @returns Array of parameter indexes (-1 if not found)\n */\nexport function getParamIndex(funcParams: string[], params: string[]): number[] {\n return params.map(param => funcParams.indexOf(param));\n}\n\n/**\n * Generate cache key based on cache name and parameters\n * @param cacheName base cache name\n * @param paramIndexes parameter indexes\n * @param paramNames parameter names\n * @param props method arguments\n * @returns generated cache key\n */\nexport function generateCacheKey(cacheName: string, paramIndexes: number[], paramNames: string[], props: any[]): string {\n let key = cacheName;\n for (let i = 0; i < paramIndexes.length; i++) {\n const paramIndex = paramIndexes[i];\n if (paramIndex >= 0 && props[paramIndex] !== undefined) {\n key += `:${paramNames[i]}:${Helper.toString(props[paramIndex])}`;\n }\n }\n return key.length > longKey ? Helper.murmurHash(key) : key;\n}\n\n/**\n * Create a delay promise\n * @param ms Delay time in milliseconds\n * @returns Promise that resolves after the specified delay\n */\nfunction delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Execute a function after a specified delay\n * @param fn Function to execute\n * @param ms Delay time in milliseconds\n * @returns Promise that resolves with the function result\n */\nexport async function asyncDelayedExecution(fn: () => any, ms: number): Promise<any> {\n await delay(ms);\n return fn();\n}","/*\n * @Author: richen\n * @Date: 2020-07-06 19:53:43\n * @LastEditTime: 2024-11-07 15:53:46\n * @Description:\n * @Copyright (c) - <richenlin(at)gmail.com>\n */\nimport { IOCContainer } from 'koatty_container';\nimport { Helper } from \"koatty_lib\";\nimport { DefaultLogger as logger } from \"koatty_logger\";\nimport { CacheStore } from \"koatty_store\";\nimport { asyncDelayedExecution, generateCacheKey, getArgs, getParamIndex } from './utils';\nimport { GetCacheStore } from './store';\n\n/**\n * @description: \n * @return {*}\n */\nexport interface CacheAbleOpt {\n // parameter name array\n params?: string[];\n // cache validity period, seconds\n timeout?: number;\n}\n\n/**\n * @description: \n * @return {*}\n */\nexport interface CacheEvictOpt {\n // parameter name array\n params?: string[];\n // enable the delayed double deletion strategy\n delayedDoubleDeletion?: boolean;\n // delay time for double deletion in milliseconds, default 5000\n delayTime?: number;\n}\n\n/**\n * Decorate this method to support caching. \n * The cache method returns a value to ensure that the next time \n * the method is executed with the same parameters, the results can be obtained\n * directly from the cache without the need to execute the method again.\n * CacheStore server config defined in db.ts.\n * \n * @export\n * @param {string} cacheName cache name\n * @param {CacheAbleOpt} [opt] cache options\n * e.g: \n * {\n * params: [\"id\"],\n * timeout: 30\n * }\n * Use the 'id' parameters of the method as cache subkeys, the cache expiration time 30s\n * @returns {MethodDecorator}\n */\nexport function CacheAble(cacheName: string, opt: CacheAbleOpt = {\n params: [],\n timeout: 300,\n}): MethodDecorator {\n return (target: any, methodName: string, descriptor: PropertyDescriptor) => {\n const componentType = IOCContainer.getType(target);\n if (![\"SERVICE\", \"COMPONENT\"].includes(componentType)) {\n throw Error(\"This decorator only used in the service、component class.\");\n }\n\n const { value, configurable, enumerable } = descriptor;\n const mergedOpt = { ...{ params: [], timeout: 300 }, ...opt };\n\n // Get the parameter list of the method\n const funcParams = getArgs((<any>target)[methodName]);\n // Get the defined parameter location\n const paramIndexes = getParamIndex(funcParams, mergedOpt.params || []);\n \n // Validate parameters\n const invalidParams: string[] = [];\n (mergedOpt.params || []).forEach((param, index) => {\n if (paramIndexes[index] === -1) {\n invalidParams.push(param);\n }\n });\n if (invalidParams.length > 0) {\n logger.Warn(`CacheAble: Parameter(s) [${invalidParams.join(\", \")}] not found in method ${String(methodName)}. These parameters will be ignored.`);\n }\n \n descriptor = {\n configurable,\n enumerable,\n writable: true,\n async value(...props: any[]) {\n const store: CacheStore = await GetCacheStore().catch((e: Error): null => {\n logger.error(\"Get cache store instance failed.\" + e.message);\n return null;\n });\n if (store) {\n const key = generateCacheKey(cacheName, paramIndexes, mergedOpt.params, props);\n const res = await store.get(key).catch((e: Error) => {\n logger.error(\"Cache get error:\" + e.message);\n });\n if (!Helper.isEmpty(res)) {\n try {\n return JSON.parse(res as string);\n } catch (e) {\n const error = e as Error;\n logger.error(\"Cache JSON parse error:\" + error.message);\n // 如果解析失败,删除损坏的缓存,重新执行方法\n store.del(key).catch((err: Error) => {\n logger.error(\"Cache del error after parse failure:\" + err.message);\n });\n }\n }\n const result = await value.apply(this, props);\n // async refresh store\n store.set(key, Helper.isJSONObj(result) ? JSON.stringify(result) : result,\n mergedOpt.timeout).catch((e: Error) => {\n logger.error(\"Cache set error:\" + e.message);\n });\n return result;\n } else {\n // tslint:disable-next-line: no-invalid-this\n return value.apply(this, props);\n }\n }\n };\n return descriptor;\n };\n}\n\n/**\n * Decorating the execution of this method will trigger a cache clear operation. \n * CacheStore server config defined in db.ts.\n *\n * @export\n * @param {string} cacheName cacheName cache name\n * @param {CacheEvictOpt} [opt] cache options\n * e.g: \n * {\n * params: [\"id\"],\n * delayedDoubleDeletion: true\n * }\n * Use the 'id' parameters of the method as cache subkeys,\n * and clear the cache after the method executed\n * @returns\n */\nexport function CacheEvict(cacheName: string, opt: CacheEvictOpt = {\n delayedDoubleDeletion: true,\n}) {\n return (target: any, methodName: string, descriptor: PropertyDescriptor) => {\n const componentType = IOCContainer.getType(target);\n if (![\"SERVICE\", \"COMPONENT\"].includes(componentType)) {\n throw Error(\"This decorator only used in the service、component class.\");\n }\n const { value, configurable, enumerable } = descriptor;\n opt = { ...{ delayedDoubleDeletion: true, }, ...opt }\n // Get the parameter list of the method\n const funcParams = getArgs((<any>target)[methodName]);\n // Get the defined parameter location\n const paramIndexes = getParamIndex(funcParams, opt.params || []);\n \n // Validate parameters\n const invalidParams: string[] = [];\n (opt.params || []).forEach((param, index) => {\n if (paramIndexes[index] === -1) {\n invalidParams.push(param);\n }\n });\n if (invalidParams.length > 0) {\n logger.Warn(`CacheEvict: Parameter(s) [${invalidParams.join(\", \")}] not found in method ${String(methodName)}. These parameters will be ignored.`);\n }\n\n descriptor = {\n configurable,\n enumerable,\n writable: true,\n async value(...props: any[]) {\n const store: CacheStore = await GetCacheStore().catch((e: Error): null => {\n logger.error(\"Get cache store instance failed.\" + e.message);\n return null;\n });\n\n if (store) {\n const key = generateCacheKey(cacheName, paramIndexes, opt.params || [], props);\n\n const result = await value.apply(this, props);\n store.del(key).catch((e: Error) => {\n logger.error(\"Cache delete error:\" + e.message);\n });\n\n if (opt.delayedDoubleDeletion) {\n const delayTime = opt.delayTime || 5000;\n asyncDelayedExecution(() => {\n store.del(key).catch((e: Error) => {\n logger.error(\"Cache double delete error:\" + e.message);\n });\n }, delayTime);\n }\n return result;\n } else {\n // If store is not available, execute method directly\n return value.apply(this, props);\n }\n }\n };\n return descriptor;\n }\n}\n","/*\n * @Description: \n * @Usage: \n * @Author: richen\n * @Date: 2024-11-07 16:00:02\n * @LastEditTime: 2024-11-07 16:00:05\n * @License: BSD (3-Clause)\n * @Copyright (c): <richenlin(at)gmail.com>\n */\nimport { Koatty } from \"koatty_core\";\nimport { StoreOptions } from \"koatty_store\";\nimport { CloseCacheStore, GetCacheStore } from \"./store\";\n\nexport * from \"./cache\";\nexport * from \"./store\";\n\n/** \n * defaultOptions\n */\n\nconst defaultOptions: StoreOptions = {\n type: \"memory\",\n db: 0,\n timeout: 30\n}\n\n/**\n * @param options - The options for the cached options\n * @param app - The Koatty application instance\n */\nexport async function KoattyCached(options: StoreOptions, app: Koatty) {\n options = { ...defaultOptions, ...options };\n\n app.once(\"appReady\", async function () {\n // 初始化缓存存储\n await GetCacheStore(options);\n });\n\n app.on(\"appStop\", async function () {\n // 关闭缓存存储\n await CloseCacheStore();\n });\n}"]}