@jintianxiayu/cache-decorator 0.1.2
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 +133 -0
- package/dist/core/cache-provider-registry.d.ts +30 -0
- package/dist/core/cache-provider-registry.d.ts.map +1 -0
- package/dist/core/cache-provider-registry.js +52 -0
- package/dist/core/cache-provider-registry.js.map +1 -0
- package/dist/core/cache-provider.d.ts +34 -0
- package/dist/core/cache-provider.d.ts.map +1 -0
- package/dist/core/cache-provider.js +3 -0
- package/dist/core/cache-provider.js.map +1 -0
- package/dist/core/key-builder.d.ts +14 -0
- package/dist/core/key-builder.d.ts.map +1 -0
- package/dist/core/key-builder.js +38 -0
- package/dist/core/key-builder.js.map +1 -0
- package/dist/core/native-cache.d.ts +18 -0
- package/dist/core/native-cache.d.ts.map +1 -0
- package/dist/core/native-cache.js +46 -0
- package/dist/core/native-cache.js.map +1 -0
- package/dist/core/pending-cache.d.ts +12 -0
- package/dist/core/pending-cache.d.ts.map +1 -0
- package/dist/core/pending-cache.js +29 -0
- package/dist/core/pending-cache.js.map +1 -0
- package/dist/core/redis-cache.d.ts +20 -0
- package/dist/core/redis-cache.d.ts.map +1 -0
- package/dist/core/redis-cache.js +58 -0
- package/dist/core/redis-cache.js.map +1 -0
- package/dist/decorators/cache-evict.d.ts +23 -0
- package/dist/decorators/cache-evict.d.ts.map +1 -0
- package/dist/decorators/cache-evict.js +54 -0
- package/dist/decorators/cache-evict.js.map +1 -0
- package/dist/decorators/cache.d.ts +37 -0
- package/dist/decorators/cache.d.ts.map +1 -0
- package/dist/decorators/cache.js +74 -0
- package/dist/decorators/cache.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/jest.config.js +14 -0
- package/package.json +30 -0
- package/src/core/cache-provider-registry.ts +53 -0
- package/src/core/cache-provider.ts +37 -0
- package/src/core/key-builder.ts +31 -0
- package/src/core/native-cache.ts +53 -0
- package/src/core/pending-cache.ts +26 -0
- package/src/core/redis-cache.ts +62 -0
- package/src/decorators/cache-evict.ts +73 -0
- package/src/decorators/cache.ts +129 -0
- package/src/index.ts +9 -0
- package/test/cache-evict.test.ts +178 -0
- package/test/cache-provider-registry.test.ts +36 -0
- package/test/cache.test.ts +256 -0
- package/test/key-builder.test.ts +37 -0
- package/test/native-cache.test.ts +71 -0
- package/test/pending-cache.test.ts +56 -0
- package/tsconfig.json +8 -0
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# @jintianxiayu/cache-decorator
|
|
2
|
+
|
|
3
|
+
方法缓存装饰器,为 TypeScript 方法提供声明式缓存功能。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @jintianxiayu/cache-decorator reflect-metadata
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 特性
|
|
12
|
+
|
|
13
|
+
- `@Cache` 装饰器:方法缓存,支持 TTL 过期
|
|
14
|
+
- `@CacheEvict` 装饰器:缓存清除
|
|
15
|
+
- 可插拔的缓存后端(Memory / Redis / 自定义)
|
|
16
|
+
- 请求合并:并发场景下返回同一个 Promise
|
|
17
|
+
- 错误结果缓存:防止缓存穿透
|
|
18
|
+
|
|
19
|
+
## 重要提示
|
|
20
|
+
|
|
21
|
+
> ⚠️ **@Cache 和 @CacheEvict 装饰器仅适用于返回 Promise 的方法**
|
|
22
|
+
>
|
|
23
|
+
> 这两个装饰器都会将被装饰的方法替换为异步函数。如果装饰返回非 Promise 的同步方法,调用方会收到 Promise 对象而非期望的返回值,导致难以排查的 bug。
|
|
24
|
+
>
|
|
25
|
+
> ```typescript
|
|
26
|
+
> // ✅ 正确:async 方法或返回 Promise 的方法
|
|
27
|
+
> @Cache('data')
|
|
28
|
+
> async getData() { ... }
|
|
29
|
+
>
|
|
30
|
+
> @CacheEvict('data')
|
|
31
|
+
> async clearData() { ... }
|
|
32
|
+
>
|
|
33
|
+
> // ❌ 错误:返回非 Promise 的同步方法不要使用这些装饰器
|
|
34
|
+
> @Cache('data')
|
|
35
|
+
> getData() { return 'result'; } // 调用方得到 Promise,不是 'result'
|
|
36
|
+
> ```
|
|
37
|
+
|
|
38
|
+
## 使用示例
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import 'reflect-metadata';
|
|
42
|
+
import { Cache, CacheEvict, CacheProviderRegistry, MemoryCacheProvider } from '@jintianxiayu/cache-decorator';
|
|
43
|
+
|
|
44
|
+
// 注册默认 Provider
|
|
45
|
+
CacheProviderRegistry.register('memory', new MemoryCacheProvider());
|
|
46
|
+
CacheProviderRegistry.setDefault('memory');
|
|
47
|
+
|
|
48
|
+
class UserService {
|
|
49
|
+
@Cache('user-cache', { ttl: 60000 })
|
|
50
|
+
async getUser(id: number) {
|
|
51
|
+
return { id, name: 'test' };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@CacheEvict('user-cache')
|
|
55
|
+
async updateUser(id: number) {
|
|
56
|
+
return { id, updated: true };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 自定义缓存 Key
|
|
62
|
+
|
|
63
|
+
通过 `key` 选项自定义缓存 key 生成逻辑:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
class UserService {
|
|
67
|
+
// 使用字符串作为 key,所有调用共享同一缓存
|
|
68
|
+
@Cache('config', { key: 'global-config' })
|
|
69
|
+
async getConfig() {
|
|
70
|
+
return { ... };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 使用函数基于参数生成 key
|
|
74
|
+
@Cache('user', { key: (...args) => String(args[0]) })
|
|
75
|
+
async getUser(id: number) {
|
|
76
|
+
return { id };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 清除时使用相同的 key 函数
|
|
80
|
+
@CacheEvict('user', { key: (...args) => String(args[0]) })
|
|
81
|
+
async deleteUser(id: number) {
|
|
82
|
+
return { id, deleted: true };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
## API
|
|
90
|
+
|
|
91
|
+
### @Cache(cacheName, options?)
|
|
92
|
+
|
|
93
|
+
缓存装饰器。**必须用于 async 方法**。
|
|
94
|
+
|
|
95
|
+
- `cacheName`: 缓存名称
|
|
96
|
+
- `options.ttl`: 过期时间(秒)
|
|
97
|
+
- `options.providerName`: 指定 CacheProvider
|
|
98
|
+
- `options.key`: 自定义缓存 key,支持以下形式:
|
|
99
|
+
- `undefined/null`: 使用默认逻辑,基于方法参数生成 key
|
|
100
|
+
- `string`: 直接作为 key 值,格式为 `cacheName:keyValue`
|
|
101
|
+
- `function`: 接收方法参数数组,返回自定义字符串
|
|
102
|
+
|
|
103
|
+
### @CacheEvict(cacheName, options?)
|
|
104
|
+
|
|
105
|
+
缓存清除装饰器。**必须用于返回 Promise 的方法**。
|
|
106
|
+
|
|
107
|
+
- `cacheName`: 缓存名称
|
|
108
|
+
- `options.allEntries`: 清除该缓存名称下的所有条目(而非所有缓存),默认 false
|
|
109
|
+
- `options.providerName`: 指定 CacheProvider
|
|
110
|
+
- `options.key`: 自定义缓存 key,与 `@Cache` 行为一致。当 `allEntries: true` 时忽略
|
|
111
|
+
|
|
112
|
+
### CacheProviderRegistry
|
|
113
|
+
|
|
114
|
+
全局缓存提供者注册表。
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
CacheProviderRegistry.register('memory', new MemoryCacheProvider());
|
|
118
|
+
CacheProviderRegistry.setDefault('memory');
|
|
119
|
+
CacheProviderRegistry.get('memory');
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### MemoryCacheProvider
|
|
123
|
+
|
|
124
|
+
内存 Map 实现,适用于单机应用。
|
|
125
|
+
|
|
126
|
+
### RedisCacheProvider
|
|
127
|
+
|
|
128
|
+
Redis 实现,适用于分布式场景。
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import Redis from 'ioredis';
|
|
132
|
+
const redisProvider = new RedisCacheProvider(new Redis());
|
|
133
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { CacheProvider } from './cache-provider';
|
|
2
|
+
/**
|
|
3
|
+
* 全局缓存提供者注册表
|
|
4
|
+
* 用于注册和获取不同类型的 CacheProvider
|
|
5
|
+
*/
|
|
6
|
+
export declare class CacheProviderRegistry {
|
|
7
|
+
/**
|
|
8
|
+
* 注册缓存提供者
|
|
9
|
+
* @param name 提供者名称
|
|
10
|
+
* @param provider 缓存提供者实例
|
|
11
|
+
*/
|
|
12
|
+
static register(name: string, provider: CacheProvider): void;
|
|
13
|
+
/**
|
|
14
|
+
* 获取缓存提供者
|
|
15
|
+
* @param name 提供者名称,不指定则使用默认提供者
|
|
16
|
+
* @returns 缓存提供者实例
|
|
17
|
+
* @throws 未注册且无默认提供者时抛出错误
|
|
18
|
+
*/
|
|
19
|
+
static get(name?: string): CacheProvider;
|
|
20
|
+
/**
|
|
21
|
+
* 设置默认缓存提供者
|
|
22
|
+
* @param name 提供者名称
|
|
23
|
+
*/
|
|
24
|
+
static setDefault(name: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* 清空注册表
|
|
27
|
+
*/
|
|
28
|
+
static clear(): void;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=cache-provider-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-provider-registry.d.ts","sourceRoot":"","sources":["../../src/core/cache-provider-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAKjD;;;GAGG;AACH,qBAAa,qBAAqB;IAChC;;;;OAIG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAI5D;;;;;OAKG;IACH,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa;IAYxC;;;OAGG;IACH,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIrC;;OAEG;IACH,MAAM,CAAC,KAAK,IAAI,IAAI;CAIrB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CacheProviderRegistry = void 0;
|
|
4
|
+
const providers = new Map();
|
|
5
|
+
let defaultName;
|
|
6
|
+
/**
|
|
7
|
+
* 全局缓存提供者注册表
|
|
8
|
+
* 用于注册和获取不同类型的 CacheProvider
|
|
9
|
+
*/
|
|
10
|
+
class CacheProviderRegistry {
|
|
11
|
+
/**
|
|
12
|
+
* 注册缓存提供者
|
|
13
|
+
* @param name 提供者名称
|
|
14
|
+
* @param provider 缓存提供者实例
|
|
15
|
+
*/
|
|
16
|
+
static register(name, provider) {
|
|
17
|
+
providers.set(name, provider);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 获取缓存提供者
|
|
21
|
+
* @param name 提供者名称,不指定则使用默认提供者
|
|
22
|
+
* @returns 缓存提供者实例
|
|
23
|
+
* @throws 未注册且无默认提供者时抛出错误
|
|
24
|
+
*/
|
|
25
|
+
static get(name) {
|
|
26
|
+
const providerName = name || defaultName;
|
|
27
|
+
if (!providerName) {
|
|
28
|
+
throw new Error('No CacheProvider registered and no default set');
|
|
29
|
+
}
|
|
30
|
+
const provider = providers.get(providerName);
|
|
31
|
+
if (!provider) {
|
|
32
|
+
throw new Error(`CacheProvider "${providerName}" not found`);
|
|
33
|
+
}
|
|
34
|
+
return provider;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 设置默认缓存提供者
|
|
38
|
+
* @param name 提供者名称
|
|
39
|
+
*/
|
|
40
|
+
static setDefault(name) {
|
|
41
|
+
defaultName = name;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 清空注册表
|
|
45
|
+
*/
|
|
46
|
+
static clear() {
|
|
47
|
+
providers.clear();
|
|
48
|
+
defaultName = undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.CacheProviderRegistry = CacheProviderRegistry;
|
|
52
|
+
//# sourceMappingURL=cache-provider-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-provider-registry.js","sourceRoot":"","sources":["../../src/core/cache-provider-registry.ts"],"names":[],"mappings":";;;AAEA,MAAM,SAAS,GAAG,IAAI,GAAG,EAAyB,CAAC;AACnD,IAAI,WAA+B,CAAC;AAEpC;;;GAGG;AACH,MAAa,qBAAqB;IAChC;;;;OAIG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAY,EAAE,QAAuB;QACnD,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,GAAG,CAAC,IAAa;QACtB,MAAM,YAAY,GAAG,IAAI,IAAI,WAAW,CAAC;QACzC,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QACD,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,kBAAkB,YAAY,aAAa,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,UAAU,CAAC,IAAY;QAC5B,WAAW,GAAG,IAAI,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK;QACV,SAAS,CAAC,KAAK,EAAE,CAAC;QAClB,WAAW,GAAG,SAAS,CAAC;IAC1B,CAAC;CACF;AA3CD,sDA2CC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 缓存提供者接口,定义缓存存储后端的统一契约
|
|
3
|
+
* 支持可插拔的缓存实现(Memory、Redis、自定义)
|
|
4
|
+
*/
|
|
5
|
+
export interface CacheProvider {
|
|
6
|
+
/**
|
|
7
|
+
* 获取缓存值
|
|
8
|
+
* @param key 缓存键
|
|
9
|
+
* @returns 缓存值,不存在或已过期返回 undefined
|
|
10
|
+
*/
|
|
11
|
+
get<T>(key: string): T | undefined | Promise<T | undefined>;
|
|
12
|
+
/**
|
|
13
|
+
* 设置缓存值
|
|
14
|
+
* @param key 缓存键
|
|
15
|
+
* @param value 缓存值
|
|
16
|
+
* @param ttl 过期时间(秒),不设置则永不过期
|
|
17
|
+
*/
|
|
18
|
+
set<T>(key: string, value: T, ttl?: number): void | Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* 删除指定缓存
|
|
21
|
+
* @param key 缓存键
|
|
22
|
+
*/
|
|
23
|
+
delete(key: string): void | Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* 清除所有缓存
|
|
26
|
+
*/
|
|
27
|
+
clear(): void | Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* 根据模式删除匹配的缓存键
|
|
30
|
+
* @param pattern glob模式字符串(如 user:*),末尾的 * 作为前缀匹配
|
|
31
|
+
*/
|
|
32
|
+
deleteByPattern(pattern: string): void | Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=cache-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-provider.d.ts","sourceRoot":"","sources":["../../src/core/cache-provider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAE5D;;;;;OAKG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElE;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C;;OAEG;IACH,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9B;;;OAGG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-provider.js","sourceRoot":"","sources":["../../src/core/cache-provider.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 缓存 Key 构建器
|
|
3
|
+
* 负责将缓存名称和参数转换为统一的 key 字符串
|
|
4
|
+
*/
|
|
5
|
+
export declare class KeyBuilder {
|
|
6
|
+
/**
|
|
7
|
+
* 构建缓存 key
|
|
8
|
+
* @param cacheName 缓存名称
|
|
9
|
+
* @param args 方法参数列表
|
|
10
|
+
* @returns 格式为 {cacheName}:{serializedArgs} 的 key 字符串
|
|
11
|
+
*/
|
|
12
|
+
static build(cacheName: string, args: unknown[]): string;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=key-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-builder.d.ts","sourceRoot":"","sources":["../../src/core/key-builder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,UAAU;IACrB;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM;CAmBzD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KeyBuilder = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 缓存 Key 构建器
|
|
6
|
+
* 负责将缓存名称和参数转换为统一的 key 字符串
|
|
7
|
+
*/
|
|
8
|
+
class KeyBuilder {
|
|
9
|
+
/**
|
|
10
|
+
* 构建缓存 key
|
|
11
|
+
* @param cacheName 缓存名称
|
|
12
|
+
* @param args 方法参数列表
|
|
13
|
+
* @returns 格式为 {cacheName}:{serializedArgs} 的 key 字符串
|
|
14
|
+
*/
|
|
15
|
+
static build(cacheName, args) {
|
|
16
|
+
if (args.length === 0) {
|
|
17
|
+
return cacheName;
|
|
18
|
+
}
|
|
19
|
+
const serializedArgs = args
|
|
20
|
+
.map(arg => {
|
|
21
|
+
if (arg === null || arg === undefined)
|
|
22
|
+
return 'null';
|
|
23
|
+
if (typeof arg === 'object') {
|
|
24
|
+
try {
|
|
25
|
+
return JSON.stringify(arg);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return String(arg);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return String(arg);
|
|
32
|
+
})
|
|
33
|
+
.join('&');
|
|
34
|
+
return `${cacheName}:${serializedArgs}`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.KeyBuilder = KeyBuilder;
|
|
38
|
+
//# sourceMappingURL=key-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-builder.js","sourceRoot":"","sources":["../../src/core/key-builder.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,MAAa,UAAU;IACrB;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,SAAiB,EAAE,IAAe;QAC7C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,cAAc,GAAG,IAAI;aACxB,GAAG,CAAC,GAAG,CAAC,EAAE;YACT,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS;gBAAE,OAAO,MAAM,CAAC;YACrD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAC5B,IAAI,CAAC;oBACH,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;gBAC7B,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;YACD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC,CAAC;aACD,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,GAAG,SAAS,IAAI,cAAc,EAAE,CAAC;IAC1C,CAAC;CACF;AA1BD,gCA0BC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CacheProvider } from './cache-provider';
|
|
2
|
+
/**
|
|
3
|
+
* 内存缓存提供者,基于 Map 实现
|
|
4
|
+
* 适用于单机应用,缓存随进程重启清除
|
|
5
|
+
*/
|
|
6
|
+
export declare class MemoryCacheProvider implements CacheProvider {
|
|
7
|
+
private cache;
|
|
8
|
+
get<T>(key: string): T | undefined;
|
|
9
|
+
set<T>(key: string, value: T, ttl?: number): void;
|
|
10
|
+
delete(key: string): void;
|
|
11
|
+
clear(): void;
|
|
12
|
+
/**
|
|
13
|
+
* 根据模式删除匹配的缓存键
|
|
14
|
+
* @param pattern glob模式字符串(如 user:*),末尾的 * 作为前缀匹配
|
|
15
|
+
*/
|
|
16
|
+
deleteByPattern(pattern: string): void;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=native-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-cache.d.ts","sourceRoot":"","sources":["../../src/core/native-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAUjD;;;GAGG;AACH,qBAAa,mBAAoB,YAAW,aAAa;IACvD,OAAO,CAAC,KAAK,CAA0C;IAEvD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAUlC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAKjD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB,KAAK,IAAI,IAAI;IAIb;;;OAGG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAQvC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemoryCacheProvider = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 内存缓存提供者,基于 Map 实现
|
|
6
|
+
* 适用于单机应用,缓存随进程重启清除
|
|
7
|
+
*/
|
|
8
|
+
class MemoryCacheProvider {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.cache = new Map();
|
|
11
|
+
}
|
|
12
|
+
get(key) {
|
|
13
|
+
const entry = this.cache.get(key);
|
|
14
|
+
if (!entry)
|
|
15
|
+
return undefined;
|
|
16
|
+
if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
|
|
17
|
+
this.cache.delete(key);
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
return entry.value;
|
|
21
|
+
}
|
|
22
|
+
set(key, value, ttl) {
|
|
23
|
+
const expiresAt = ttl ? Date.now() + ttl * 1000 : null;
|
|
24
|
+
this.cache.set(key, { value, expiresAt });
|
|
25
|
+
}
|
|
26
|
+
delete(key) {
|
|
27
|
+
this.cache.delete(key);
|
|
28
|
+
}
|
|
29
|
+
clear() {
|
|
30
|
+
this.cache.clear();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 根据模式删除匹配的缓存键
|
|
34
|
+
* @param pattern glob模式字符串(如 user:*),末尾的 * 作为前缀匹配
|
|
35
|
+
*/
|
|
36
|
+
deleteByPattern(pattern) {
|
|
37
|
+
const prefix = pattern.replace(/\*$/, '');
|
|
38
|
+
for (const key of this.cache.keys()) {
|
|
39
|
+
if (key.startsWith(prefix)) {
|
|
40
|
+
this.cache.delete(key);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.MemoryCacheProvider = MemoryCacheProvider;
|
|
46
|
+
//# sourceMappingURL=native-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-cache.js","sourceRoot":"","sources":["../../src/core/native-cache.ts"],"names":[],"mappings":";;;AAUA;;;GAGG;AACH,MAAa,mBAAmB;IAAhC;QACU,UAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;IAqCzD,CAAC;IAnCC,GAAG,CAAI,GAAW;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAC7B,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YAC7D,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,KAAK,CAAC,KAAU,CAAC;IAC1B,CAAC;IAED,GAAG,CAAI,GAAW,EAAE,KAAQ,EAAE,GAAY;QACxC,MAAM,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QACvD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,OAAe;QAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC1C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YACpC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAtCD,kDAsCC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 请求合并缓存
|
|
3
|
+
* 用于在并发场景下返回同一个 Promise,避免重复执行
|
|
4
|
+
*/
|
|
5
|
+
export declare class PendingCache {
|
|
6
|
+
private pending;
|
|
7
|
+
get<T>(key: string): Promise<T> | undefined;
|
|
8
|
+
set<T>(key: string, promise: Promise<T>): void;
|
|
9
|
+
delete(key: string): void;
|
|
10
|
+
clear(): void;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=pending-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending-cache.d.ts","sourceRoot":"","sources":["../../src/core/pending-cache.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAuC;IAEtD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS;IAI3C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI;IAO9C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PendingCache = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 请求合并缓存
|
|
6
|
+
* 用于在并发场景下返回同一个 Promise,避免重复执行
|
|
7
|
+
*/
|
|
8
|
+
class PendingCache {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.pending = new Map();
|
|
11
|
+
}
|
|
12
|
+
get(key) {
|
|
13
|
+
return this.pending.get(key);
|
|
14
|
+
}
|
|
15
|
+
set(key, promise) {
|
|
16
|
+
this.pending.set(key, promise);
|
|
17
|
+
promise.finally(() => {
|
|
18
|
+
this.pending.delete(key);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
delete(key) {
|
|
22
|
+
this.pending.delete(key);
|
|
23
|
+
}
|
|
24
|
+
clear() {
|
|
25
|
+
this.pending.clear();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.PendingCache = PendingCache;
|
|
29
|
+
//# sourceMappingURL=pending-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending-cache.js","sourceRoot":"","sources":["../../src/core/pending-cache.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,MAAa,YAAY;IAAzB;QACU,YAAO,GAAG,IAAI,GAAG,EAA4B,CAAC;IAoBxD,CAAC;IAlBC,GAAG,CAAI,GAAW;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAA2B,CAAC;IACzD,CAAC;IAED,GAAG,CAAI,GAAW,EAAE,OAAmB;QACrC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC/B,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;YACnB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF;AArBD,oCAqBC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CacheProvider } from './cache-provider';
|
|
2
|
+
import Redis from 'ioredis';
|
|
3
|
+
/**
|
|
4
|
+
* Redis 缓存提供者,基于 ioredis 实现
|
|
5
|
+
* 适用于分布式场景,支持跨进程共享缓存
|
|
6
|
+
*/
|
|
7
|
+
export declare class RedisCacheProvider implements CacheProvider {
|
|
8
|
+
private redis;
|
|
9
|
+
constructor(redis?: Redis);
|
|
10
|
+
get<T>(key: string): Promise<T | undefined>;
|
|
11
|
+
set<T>(key: string, value: T, ttl?: number): Promise<void>;
|
|
12
|
+
delete(key: string): Promise<void>;
|
|
13
|
+
clear(): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* 根据模式删除匹配的缓存键
|
|
16
|
+
* @param pattern glob模式字符串(如 user:*),使用 SCAN 游标迭代避免阻塞 Redis
|
|
17
|
+
*/
|
|
18
|
+
deleteByPattern(pattern: string): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=redis-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-cache.d.ts","sourceRoot":"","sources":["../../src/core/redis-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,MAAM,SAAS,CAAC;AAE5B;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,aAAa;IACtD,OAAO,CAAC,KAAK,CAAQ;gBAET,KAAK,CAAC,EAAE,KAAK;IAInB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAU3C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS1D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;;OAGG;IACG,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAgBtD"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RedisCacheProvider = void 0;
|
|
7
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
8
|
+
/**
|
|
9
|
+
* Redis 缓存提供者,基于 ioredis 实现
|
|
10
|
+
* 适用于分布式场景,支持跨进程共享缓存
|
|
11
|
+
*/
|
|
12
|
+
class RedisCacheProvider {
|
|
13
|
+
constructor(redis) {
|
|
14
|
+
this.redis = redis ?? new ioredis_1.default();
|
|
15
|
+
}
|
|
16
|
+
async get(key) {
|
|
17
|
+
const value = await this.redis.get(key);
|
|
18
|
+
if (value === null)
|
|
19
|
+
return undefined;
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(value);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async set(key, value, ttl) {
|
|
28
|
+
const serialized = typeof value === 'string' ? value : JSON.stringify(value);
|
|
29
|
+
if (ttl) {
|
|
30
|
+
await this.redis.setex(key, ttl, serialized);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
await this.redis.set(key, serialized);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async delete(key) {
|
|
37
|
+
await this.redis.del(key);
|
|
38
|
+
}
|
|
39
|
+
async clear() {
|
|
40
|
+
await this.redis.flushdb();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 根据模式删除匹配的缓存键
|
|
44
|
+
* @param pattern glob模式字符串(如 user:*),使用 SCAN 游标迭代避免阻塞 Redis
|
|
45
|
+
*/
|
|
46
|
+
async deleteByPattern(pattern) {
|
|
47
|
+
let cursor = '0';
|
|
48
|
+
do {
|
|
49
|
+
const [nextCursor, keys] = await this.redis.scan(cursor, 'MATCH', pattern, 'COUNT', 100);
|
|
50
|
+
cursor = nextCursor;
|
|
51
|
+
if (keys.length > 0) {
|
|
52
|
+
await this.redis.del(...keys);
|
|
53
|
+
}
|
|
54
|
+
} while (cursor !== '0');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.RedisCacheProvider = RedisCacheProvider;
|
|
58
|
+
//# sourceMappingURL=redis-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-cache.js","sourceRoot":"","sources":["../../src/core/redis-cache.ts"],"names":[],"mappings":";;;;;;AACA,sDAA4B;AAE5B;;;GAGG;AACH,MAAa,kBAAkB;IAG7B,YAAY,KAAa;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,IAAI,IAAI,iBAAK,EAAE,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,GAAW;QACtB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,SAAS,CAAC;QACrC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAM,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAqB,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,GAAW,EAAE,KAAQ,EAAE,GAAY;QAC9C,MAAM,UAAU,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC7E,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,OAAe;QACnC,IAAI,MAAM,GAAG,GAAG,CAAC;QACjB,GAAG,CAAC;YACF,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAC9C,MAAM,EACN,OAAO,EACP,OAAO,EACP,OAAO,EACP,GAAG,CACJ,CAAC;YACF,MAAM,GAAG,UAAU,CAAC;YACpB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,QAAQ,MAAM,KAAK,GAAG,EAAE;IAC3B,CAAC;CACF;AAtDD,gDAsDC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CacheOptions } from './cache';
|
|
2
|
+
/**
|
|
3
|
+
* @CacheEvict 装饰器配置项
|
|
4
|
+
*/
|
|
5
|
+
export interface CacheEvictOptions extends Pick<CacheOptions, 'key'> {
|
|
6
|
+
/**
|
|
7
|
+
* 是否清除所有条目,默认为 false
|
|
8
|
+
*/
|
|
9
|
+
allEntries?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* 指定 CacheProvider 名称
|
|
12
|
+
*/
|
|
13
|
+
providerName?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 缓存清除装饰器
|
|
17
|
+
* 在方法执行后清除对应的缓存条目
|
|
18
|
+
* @param cacheName 缓存名称
|
|
19
|
+
* @param options 配置项
|
|
20
|
+
*/
|
|
21
|
+
export declare function CacheEvict(cacheName: string, options?: CacheEvictOptions): (_target: object, _propertyKey: string, descriptor: PropertyDescriptor) => void;
|
|
22
|
+
export { CacheProviderRegistry } from '../core/cache-provider-registry';
|
|
23
|
+
//# sourceMappingURL=cache-evict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-evict.d.ts","sourceRoot":"","sources":["../../src/decorators/cache-evict.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAoB,MAAM,SAAS,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC;IAClE;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAuBD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,IAErE,SAAS,MAAM,EACf,cAAc,MAAM,EACpB,YAAY,kBAAkB,UAoBjC;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CacheProviderRegistry = void 0;
|
|
4
|
+
exports.CacheEvict = CacheEvict;
|
|
5
|
+
const cache_provider_registry_1 = require("../core/cache-provider-registry");
|
|
6
|
+
const key_builder_1 = require("../core/key-builder");
|
|
7
|
+
/**
|
|
8
|
+
* 解析缓存 key
|
|
9
|
+
* @param cacheName 缓存名称
|
|
10
|
+
* @param keyResolver key 解析器
|
|
11
|
+
* @param args 方法参数数组
|
|
12
|
+
* @returns 解析后的缓存 key
|
|
13
|
+
*/
|
|
14
|
+
function resolveCacheKey(cacheName, keyResolver, args) {
|
|
15
|
+
if (keyResolver === undefined || keyResolver === null) {
|
|
16
|
+
return key_builder_1.KeyBuilder.build(cacheName, args);
|
|
17
|
+
}
|
|
18
|
+
if (typeof keyResolver === 'string') {
|
|
19
|
+
return key_builder_1.KeyBuilder.build(cacheName, [keyResolver]);
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
return key_builder_1.KeyBuilder.build(cacheName, [keyResolver(...args)]);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return key_builder_1.KeyBuilder.build(cacheName, args);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 缓存清除装饰器
|
|
30
|
+
* 在方法执行后清除对应的缓存条目
|
|
31
|
+
* @param cacheName 缓存名称
|
|
32
|
+
* @param options 配置项
|
|
33
|
+
*/
|
|
34
|
+
function CacheEvict(cacheName, options) {
|
|
35
|
+
return function (_target, _propertyKey, descriptor) {
|
|
36
|
+
const originalMethod = descriptor.value;
|
|
37
|
+
descriptor.value = async function (...args) {
|
|
38
|
+
const result = await originalMethod.apply(this, args);
|
|
39
|
+
const providerName = options?.providerName;
|
|
40
|
+
const provider = cache_provider_registry_1.CacheProviderRegistry.get(providerName);
|
|
41
|
+
if (options?.allEntries) {
|
|
42
|
+
await provider.deleteByPattern(cacheName + '*');
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const cacheKey = resolveCacheKey(cacheName, options?.key, args);
|
|
46
|
+
provider.delete(cacheKey);
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
var cache_provider_registry_2 = require("../core/cache-provider-registry");
|
|
53
|
+
Object.defineProperty(exports, "CacheProviderRegistry", { enumerable: true, get: function () { return cache_provider_registry_2.CacheProviderRegistry; } });
|
|
54
|
+
//# sourceMappingURL=cache-evict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-evict.js","sourceRoot":"","sources":["../../src/decorators/cache-evict.ts"],"names":[],"mappings":";;;AA8CA,gCAwBC;AAtED,6EAAwE;AACxE,qDAAiD;AAkBjD;;;;;;GAMG;AACH,SAAS,eAAe,CAAC,SAAiB,EAAE,WAAyC,EAAE,IAAe;IACpG,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACtD,OAAO,wBAAU,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,wBAAU,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,CAAC;QACH,OAAO,wBAAU,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,wBAAU,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,UAAU,CAAC,SAAiB,EAAE,OAA2B;IACvE,OAAO,UACL,OAAe,EACf,YAAoB,EACpB,UAA8B;QAE9B,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QAExC,UAAU,CAAC,KAAK,GAAG,KAAK,WAAW,GAAG,IAAe;YACnD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAEtD,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,CAAC;YAC3C,MAAM,QAAQ,GAAG,+CAAqB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAEzD,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;gBACxB,MAAM,QAAQ,CAAC,eAAe,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC;YAClD,CAAC;iBAAM,CAAC;gBACN,MAAM,QAAQ,GAAG,eAAe,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;gBAChE,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC5B,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED,2EAAwE;AAA/D,gIAAA,qBAAqB,OAAA"}
|