@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.
@@ -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 ttl 缓存时间
27
+ * @param ttlOrOptions 缓存时间或选项
26
28
  * @returns 返回设置的缓存内容
27
29
  */
28
- async set(key, value, ttl = this.options.ttl) {
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
- return JSON.parse(gotValue);
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 ttl 缓存时间
119
+ * @param ttlOrOptions 缓存时间或选项
106
120
  * @returns 返回获取到的内容
107
121
  */
108
- async remember(key, action, ttl = this.options.ttl) {
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, ttl);
126
+ await this.set(key, value, ttlOrOptions);
113
127
  }
114
128
  return value;
115
129
  }
116
- async rememberMany(raws, key, action, ttl = this.options.ttl) {
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, ttl);
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
- return _x.x.redis.del(...keys.map(key => this.toRedisKey(key)));
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
  /**
@@ -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 ttl 缓存时间
37
+ * @param ttlOrOptions 缓存时间或选项
31
38
  * @returns 返回设置的缓存内容
32
39
  */
33
- set<K extends TKeyPath, V extends Value<TData, K>>(key: K, value: V, ttl?: MsValue | ((data: V, defaultTTL: MsValue) => MsValue)): Promise<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 ttl 缓存时间
75
+ * @param ttlOrOptions 缓存时间或选项
68
76
  * @returns 返回获取到的内容
69
77
  */
70
- remember<K extends TKeyPath, V extends Value<TData, K>>(key: K, action: () => V | Promise<V>, ttl?: MsValue | ((data: V, defaultTTL: MsValue) => MsValue)): 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[]>, ttl?: MsValue | ((data: V, defaultTTL: MsValue) => MsValue)): 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
  *
@@ -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 ttl 缓存时间
22
+ * @param ttlOrOptions 缓存时间或选项
21
23
  * @returns 返回设置的缓存内容
22
24
  */
23
- async set(key, value, ttl = this.options.ttl) {
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
- return JSON.parse(gotValue);
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 ttl 缓存时间
114
+ * @param ttlOrOptions 缓存时间或选项
101
115
  * @returns 返回获取到的内容
102
116
  */
103
- async remember(key, action, ttl = this.options.ttl) {
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, ttl);
121
+ await this.set(key, value, ttlOrOptions);
108
122
  }
109
123
  return value;
110
124
  }
111
- async rememberMany(raws, key, action, ttl = this.options.ttl) {
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, ttl);
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
- return x.redis.del(...keys.map(key => this.toRedisKey(key)));
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
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jayfong/x-server",
3
- "version": "2.16.5",
3
+ "version": "2.17.1",
4
4
  "license": "ISC",
5
5
  "sideEffects": false,
6
6
  "main": "lib/_cjs/index.js",