@jayfong/x-server 2.16.5 → 2.17.1
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/lib/_cjs/services/cache.js +29 -9
- package/lib/services/cache.d.ts +14 -6
- package/lib/services/cache.js +29 -9
- package/package.json +1 -1
|
@@ -11,7 +11,9 @@ class CacheService {
|
|
|
11
11
|
this.options = options;
|
|
12
12
|
this.serviceName = 'cache';
|
|
13
13
|
this.prefix = void 0;
|
|
14
|
+
this.memoryCache = void 0;
|
|
14
15
|
this.prefix = `${_x.x.appId}:`;
|
|
16
|
+
this.memoryCache = !options.memory ? undefined : new Map();
|
|
15
17
|
}
|
|
16
18
|
toRedisKey(key) {
|
|
17
19
|
return `${this.prefix}${Array.isArray(key) ? key.join('_') : String(key)}`;
|
|
@@ -22,10 +24,11 @@ class CacheService {
|
|
|
22
24
|
*
|
|
23
25
|
* @param key 键
|
|
24
26
|
* @param value 值
|
|
25
|
-
* @param
|
|
27
|
+
* @param ttlOrOptions 缓存时间或选项
|
|
26
28
|
* @returns 返回设置的缓存内容
|
|
27
29
|
*/
|
|
28
|
-
async set(key, value,
|
|
30
|
+
async set(key, value, ttlOrOptions) {
|
|
31
|
+
const ttl = ttlOrOptions == null ? this.options.ttl : typeof ttlOrOptions === 'object' ? ttlOrOptions.ttl : ttlOrOptions;
|
|
29
32
|
const redisTtl = typeof ttl === 'function' ? ttl(value, this.options.ttl) : ttl;
|
|
30
33
|
if (redisTtl) {
|
|
31
34
|
const redisKey = this.toRedisKey(key);
|
|
@@ -33,6 +36,9 @@ class CacheService {
|
|
|
33
36
|
await _x.x.redis.set(redisKey, redisValue,
|
|
34
37
|
// 毫秒
|
|
35
38
|
'PX', (0, _vtils.ms)(redisTtl));
|
|
39
|
+
if (this.options.memory) {
|
|
40
|
+
this.memoryCache.set(redisKey, value);
|
|
41
|
+
}
|
|
36
42
|
}
|
|
37
43
|
return value;
|
|
38
44
|
}
|
|
@@ -53,14 +59,22 @@ class CacheService {
|
|
|
53
59
|
* 获取缓存内容。
|
|
54
60
|
*
|
|
55
61
|
* @param key 键
|
|
62
|
+
* @param options 选项
|
|
56
63
|
* @returns 返回获取到的缓存内容
|
|
57
64
|
*/
|
|
58
65
|
async get(key) {
|
|
59
66
|
const redisKey = this.toRedisKey(key);
|
|
67
|
+
if (this.options.memory && this.memoryCache.has(redisKey)) {
|
|
68
|
+
return this.memoryCache.get(redisKey);
|
|
69
|
+
}
|
|
60
70
|
const gotValue = await _x.x.redis.get(redisKey);
|
|
61
71
|
if (gotValue) {
|
|
62
72
|
try {
|
|
63
|
-
|
|
73
|
+
const parsedValue = JSON.parse(gotValue);
|
|
74
|
+
if (this.options.memory) {
|
|
75
|
+
this.memoryCache.set(redisKey, parsedValue);
|
|
76
|
+
}
|
|
77
|
+
return parsedValue;
|
|
64
78
|
} catch {}
|
|
65
79
|
}
|
|
66
80
|
return null;
|
|
@@ -102,18 +116,18 @@ class CacheService {
|
|
|
102
116
|
*
|
|
103
117
|
* @param key 键
|
|
104
118
|
* @param action 获取缓存内容的操作
|
|
105
|
-
* @param
|
|
119
|
+
* @param ttlOrOptions 缓存时间或选项
|
|
106
120
|
* @returns 返回获取到的内容
|
|
107
121
|
*/
|
|
108
|
-
async remember(key, action,
|
|
122
|
+
async remember(key, action, ttlOrOptions) {
|
|
109
123
|
let value = await this.get(key);
|
|
110
124
|
if (value === null) {
|
|
111
125
|
value = await action();
|
|
112
|
-
await this.set(key, value,
|
|
126
|
+
await this.set(key, value, ttlOrOptions);
|
|
113
127
|
}
|
|
114
128
|
return value;
|
|
115
129
|
}
|
|
116
|
-
async rememberMany(raws, key, action,
|
|
130
|
+
async rememberMany(raws, key, action, ttlOrOptions) {
|
|
117
131
|
const keys = raws.map(key);
|
|
118
132
|
const values = await this.getMany(...keys);
|
|
119
133
|
const shouldUpdateIndexes = [];
|
|
@@ -126,7 +140,7 @@ class CacheService {
|
|
|
126
140
|
const nextValues = await action(shouldUpdateIndexes.map(i => raws[i]));
|
|
127
141
|
await Promise.all(nextValues.map(async (nextValue, index) => {
|
|
128
142
|
values[shouldUpdateIndexes[index]] = nextValue;
|
|
129
|
-
await this.set(keys[shouldUpdateIndexes[index]], nextValue,
|
|
143
|
+
await this.set(keys[shouldUpdateIndexes[index]], nextValue, ttlOrOptions);
|
|
130
144
|
}));
|
|
131
145
|
}
|
|
132
146
|
return values;
|
|
@@ -193,7 +207,13 @@ class CacheService {
|
|
|
193
207
|
if (!keys.length) {
|
|
194
208
|
return 0;
|
|
195
209
|
}
|
|
196
|
-
|
|
210
|
+
const redisKeys = keys.map(key => this.toRedisKey(key));
|
|
211
|
+
if (this.options.memory) {
|
|
212
|
+
redisKeys.forEach(redisKey => {
|
|
213
|
+
this.memoryCache.delete(redisKey);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return _x.x.redis.del(...redisKeys);
|
|
197
217
|
}
|
|
198
218
|
|
|
199
219
|
/**
|
package/lib/services/cache.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { MsValue } from 'vtils';
|
|
1
2
|
import { AsyncOrSync, IsEmptyArray } from 'vtils/types';
|
|
2
3
|
import { BaseService } from './base';
|
|
3
|
-
import { MsValue } from 'vtils';
|
|
4
4
|
export interface CacheServiceOptions {
|
|
5
5
|
/** 默认过期时间 */
|
|
6
6
|
ttl: MsValue;
|
|
7
|
+
/** 启用内存缓存,仅 get, set, remove, remember 支持 */
|
|
8
|
+
memory?: boolean;
|
|
7
9
|
}
|
|
8
10
|
type Data = {
|
|
9
11
|
[K in string]: (...args: any[]) => any;
|
|
@@ -16,10 +18,15 @@ type KeyPathForNumberValue<T extends Data> = {
|
|
|
16
18
|
[K in keyof T]: T[K] extends (...args: infer X) => number ? IsEmptyArray<X> extends true ? K : [K, ...X] : never;
|
|
17
19
|
}[keyof T];
|
|
18
20
|
type Value<T extends Data, P extends KeyPath<T>> = ReturnType<T[P extends any[] ? P[0] : P]>;
|
|
21
|
+
type CacheSetTTL<V> = MsValue | ((data: V, defaultTTL: MsValue) => MsValue);
|
|
22
|
+
type CacheSetOptions<V> = CacheSetTTL<V> | {
|
|
23
|
+
ttl?: CacheSetTTL<V>;
|
|
24
|
+
};
|
|
19
25
|
export declare class CacheService<TData extends Data = Data, TKey extends Key<TData> = any, TKeyPath extends KeyPath<TData> = any, TKeyPathForNumberValue extends KeyPathForNumberValue<TData> = any> implements BaseService {
|
|
20
26
|
options: CacheServiceOptions;
|
|
21
27
|
serviceName: string;
|
|
22
28
|
private prefix;
|
|
29
|
+
private memoryCache;
|
|
23
30
|
constructor(options: CacheServiceOptions);
|
|
24
31
|
private toRedisKey;
|
|
25
32
|
/**
|
|
@@ -27,10 +34,10 @@ export declare class CacheService<TData extends Data = Data, TKey extends Key<TD
|
|
|
27
34
|
*
|
|
28
35
|
* @param key 键
|
|
29
36
|
* @param value 值
|
|
30
|
-
* @param
|
|
37
|
+
* @param ttlOrOptions 缓存时间或选项
|
|
31
38
|
* @returns 返回设置的缓存内容
|
|
32
39
|
*/
|
|
33
|
-
set<K extends TKeyPath, V extends Value<TData, K>>(key: K, value: V,
|
|
40
|
+
set<K extends TKeyPath, V extends Value<TData, K>>(key: K, value: V, ttlOrOptions?: CacheSetOptions<V>): Promise<V>;
|
|
34
41
|
/**
|
|
35
42
|
* 存储值然后返回其对应的键,该键 URL 友好。
|
|
36
43
|
*
|
|
@@ -42,6 +49,7 @@ export declare class CacheService<TData extends Data = Data, TKey extends Key<TD
|
|
|
42
49
|
* 获取缓存内容。
|
|
43
50
|
*
|
|
44
51
|
* @param key 键
|
|
52
|
+
* @param options 选项
|
|
45
53
|
* @returns 返回获取到的缓存内容
|
|
46
54
|
*/
|
|
47
55
|
get<K extends TKeyPath, V extends Value<TData, K>>(key: K): Promise<V | null>;
|
|
@@ -64,11 +72,11 @@ export declare class CacheService<TData extends Data = Data, TKey extends Key<TD
|
|
|
64
72
|
*
|
|
65
73
|
* @param key 键
|
|
66
74
|
* @param action 获取缓存内容的操作
|
|
67
|
-
* @param
|
|
75
|
+
* @param ttlOrOptions 缓存时间或选项
|
|
68
76
|
* @returns 返回获取到的内容
|
|
69
77
|
*/
|
|
70
|
-
remember<K extends TKeyPath, V extends Value<TData, K>>(key: K, action: () => V | Promise<V>,
|
|
71
|
-
rememberMany<T, K extends TKeyPath, V extends Value<TData, K>>(raws: T[], key: (raw: T) => K, action: (raws: T[]) => V[] | Promise<V[]>,
|
|
78
|
+
remember<K extends TKeyPath, V extends Value<TData, K>>(key: K, action: () => V | Promise<V>, ttlOrOptions?: CacheSetOptions<V>): Promise<V>;
|
|
79
|
+
rememberMany<T, K extends TKeyPath, V extends Value<TData, K>>(raws: T[], key: (raw: T) => K, action: (raws: T[]) => V[] | Promise<V[]>, ttlOrOptions?: CacheSetOptions<V>): Promise<V[]>;
|
|
72
80
|
/**
|
|
73
81
|
* 自增。
|
|
74
82
|
*
|
package/lib/services/cache.js
CHANGED
|
@@ -6,7 +6,9 @@ export class CacheService {
|
|
|
6
6
|
this.options = options;
|
|
7
7
|
this.serviceName = 'cache';
|
|
8
8
|
this.prefix = void 0;
|
|
9
|
+
this.memoryCache = void 0;
|
|
9
10
|
this.prefix = `${x.appId}:`;
|
|
11
|
+
this.memoryCache = !options.memory ? undefined : new Map();
|
|
10
12
|
}
|
|
11
13
|
toRedisKey(key) {
|
|
12
14
|
return `${this.prefix}${Array.isArray(key) ? key.join('_') : String(key)}`;
|
|
@@ -17,10 +19,11 @@ export class CacheService {
|
|
|
17
19
|
*
|
|
18
20
|
* @param key 键
|
|
19
21
|
* @param value 值
|
|
20
|
-
* @param
|
|
22
|
+
* @param ttlOrOptions 缓存时间或选项
|
|
21
23
|
* @returns 返回设置的缓存内容
|
|
22
24
|
*/
|
|
23
|
-
async set(key, value,
|
|
25
|
+
async set(key, value, ttlOrOptions) {
|
|
26
|
+
const ttl = ttlOrOptions == null ? this.options.ttl : typeof ttlOrOptions === 'object' ? ttlOrOptions.ttl : ttlOrOptions;
|
|
24
27
|
const redisTtl = typeof ttl === 'function' ? ttl(value, this.options.ttl) : ttl;
|
|
25
28
|
if (redisTtl) {
|
|
26
29
|
const redisKey = this.toRedisKey(key);
|
|
@@ -28,6 +31,9 @@ export class CacheService {
|
|
|
28
31
|
await x.redis.set(redisKey, redisValue,
|
|
29
32
|
// 毫秒
|
|
30
33
|
'PX', ms(redisTtl));
|
|
34
|
+
if (this.options.memory) {
|
|
35
|
+
this.memoryCache.set(redisKey, value);
|
|
36
|
+
}
|
|
31
37
|
}
|
|
32
38
|
return value;
|
|
33
39
|
}
|
|
@@ -48,14 +54,22 @@ export class CacheService {
|
|
|
48
54
|
* 获取缓存内容。
|
|
49
55
|
*
|
|
50
56
|
* @param key 键
|
|
57
|
+
* @param options 选项
|
|
51
58
|
* @returns 返回获取到的缓存内容
|
|
52
59
|
*/
|
|
53
60
|
async get(key) {
|
|
54
61
|
const redisKey = this.toRedisKey(key);
|
|
62
|
+
if (this.options.memory && this.memoryCache.has(redisKey)) {
|
|
63
|
+
return this.memoryCache.get(redisKey);
|
|
64
|
+
}
|
|
55
65
|
const gotValue = await x.redis.get(redisKey);
|
|
56
66
|
if (gotValue) {
|
|
57
67
|
try {
|
|
58
|
-
|
|
68
|
+
const parsedValue = JSON.parse(gotValue);
|
|
69
|
+
if (this.options.memory) {
|
|
70
|
+
this.memoryCache.set(redisKey, parsedValue);
|
|
71
|
+
}
|
|
72
|
+
return parsedValue;
|
|
59
73
|
} catch {}
|
|
60
74
|
}
|
|
61
75
|
return null;
|
|
@@ -97,18 +111,18 @@ export class CacheService {
|
|
|
97
111
|
*
|
|
98
112
|
* @param key 键
|
|
99
113
|
* @param action 获取缓存内容的操作
|
|
100
|
-
* @param
|
|
114
|
+
* @param ttlOrOptions 缓存时间或选项
|
|
101
115
|
* @returns 返回获取到的内容
|
|
102
116
|
*/
|
|
103
|
-
async remember(key, action,
|
|
117
|
+
async remember(key, action, ttlOrOptions) {
|
|
104
118
|
let value = await this.get(key);
|
|
105
119
|
if (value === null) {
|
|
106
120
|
value = await action();
|
|
107
|
-
await this.set(key, value,
|
|
121
|
+
await this.set(key, value, ttlOrOptions);
|
|
108
122
|
}
|
|
109
123
|
return value;
|
|
110
124
|
}
|
|
111
|
-
async rememberMany(raws, key, action,
|
|
125
|
+
async rememberMany(raws, key, action, ttlOrOptions) {
|
|
112
126
|
const keys = raws.map(key);
|
|
113
127
|
const values = await this.getMany(...keys);
|
|
114
128
|
const shouldUpdateIndexes = [];
|
|
@@ -121,7 +135,7 @@ export class CacheService {
|
|
|
121
135
|
const nextValues = await action(shouldUpdateIndexes.map(i => raws[i]));
|
|
122
136
|
await Promise.all(nextValues.map(async (nextValue, index) => {
|
|
123
137
|
values[shouldUpdateIndexes[index]] = nextValue;
|
|
124
|
-
await this.set(keys[shouldUpdateIndexes[index]], nextValue,
|
|
138
|
+
await this.set(keys[shouldUpdateIndexes[index]], nextValue, ttlOrOptions);
|
|
125
139
|
}));
|
|
126
140
|
}
|
|
127
141
|
return values;
|
|
@@ -188,7 +202,13 @@ export class CacheService {
|
|
|
188
202
|
if (!keys.length) {
|
|
189
203
|
return 0;
|
|
190
204
|
}
|
|
191
|
-
|
|
205
|
+
const redisKeys = keys.map(key => this.toRedisKey(key));
|
|
206
|
+
if (this.options.memory) {
|
|
207
|
+
redisKeys.forEach(redisKey => {
|
|
208
|
+
this.memoryCache.delete(redisKey);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
return x.redis.del(...redisKeys);
|
|
192
212
|
}
|
|
193
213
|
|
|
194
214
|
/**
|