@zenweb/cache 4.4.0 → 4.6.0
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/cache.d.ts +18 -7
- package/dist/cache.js +134 -91
- package/dist/index.js +2 -12
- package/dist/options.d.ts +7 -0
- package/dist/options.js +36 -0
- package/dist/types.d.ts +26 -7
- package/package.json +3 -2
package/dist/cache.d.ts
CHANGED
|
@@ -17,15 +17,19 @@ export declare class CacheResult {
|
|
|
17
17
|
* 对象缓存系统
|
|
18
18
|
*/
|
|
19
19
|
export declare class Cache {
|
|
20
|
-
|
|
21
|
-
private option
|
|
22
|
-
constructor(redis: Redis, option
|
|
20
|
+
redis: Redis;
|
|
21
|
+
private option;
|
|
22
|
+
constructor(redis: Redis, option: Required<SetupOption>);
|
|
23
|
+
/**
|
|
24
|
+
* 取得缓存剩余有效期
|
|
25
|
+
*/
|
|
26
|
+
ttl(key: string): Promise<number>;
|
|
23
27
|
/**
|
|
24
28
|
* 删除缓存
|
|
25
29
|
*/
|
|
26
30
|
del(key: string): Promise<number>;
|
|
27
31
|
/**
|
|
28
|
-
* 直接设置缓存 -
|
|
32
|
+
* 直接设置缓存 - 不经过序列化的数据
|
|
29
33
|
* @param key
|
|
30
34
|
* @param value
|
|
31
35
|
* @param ttl 缓存有效时长 (秒),不设置取默认设置
|
|
@@ -34,7 +38,7 @@ export declare class Cache {
|
|
|
34
38
|
/**
|
|
35
39
|
* 缓存对象
|
|
36
40
|
* @param key 缓存key
|
|
37
|
-
* @param value 缓存值,除了 `Buffer`
|
|
41
|
+
* @param value 缓存值,除了 `Buffer` 以外的值会经过序列化
|
|
38
42
|
* @param ttlopt 缓存有效时长 (秒),不设置取默认设置 | 缓存选项
|
|
39
43
|
*/
|
|
40
44
|
set(key: string, value: any, ttlopt?: number | SetOption): Promise<SetResult>;
|
|
@@ -59,10 +63,17 @@ export declare class Cache {
|
|
|
59
63
|
* @param key 缓存KEY
|
|
60
64
|
* @param fetch 缓存设置方法回调
|
|
61
65
|
*/
|
|
62
|
-
lockGet<T = unknown>(key: string, fetch: () => Promise<T> | T,
|
|
66
|
+
lockGet<T = unknown>(key: string, fetch: () => Promise<T> | T, opt: {
|
|
67
|
+
parse: false;
|
|
68
|
+
noWait: true;
|
|
69
|
+
} & LockGetOption): Promise<CacheResult | undefined>;
|
|
70
|
+
lockGet<T = unknown>(key: string, fetch: () => Promise<T> | T, opt: {
|
|
71
|
+
noWait: true;
|
|
72
|
+
} & LockGetOption): Promise<T | undefined>;
|
|
73
|
+
lockGet<T = unknown>(key: string, fetch: () => Promise<T> | T, opt: {
|
|
63
74
|
parse: false;
|
|
64
75
|
} & LockGetOption): Promise<CacheResult>;
|
|
65
|
-
lockGet<T = unknown>(key: string, fetch: () => Promise<T> | T,
|
|
76
|
+
lockGet<T = unknown>(key: string, fetch: () => Promise<T> | T, opt?: {
|
|
66
77
|
parse?: true;
|
|
67
78
|
} & LockGetOption): Promise<T>;
|
|
68
79
|
/**
|
package/dist/cache.js
CHANGED
|
@@ -33,6 +33,12 @@ class Cache {
|
|
|
33
33
|
this.redis = redis;
|
|
34
34
|
this.option = option;
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* 取得缓存剩余有效期
|
|
38
|
+
*/
|
|
39
|
+
ttl(key) {
|
|
40
|
+
return this.redis.ttl(key);
|
|
41
|
+
}
|
|
36
42
|
/**
|
|
37
43
|
* 删除缓存
|
|
38
44
|
*/
|
|
@@ -40,7 +46,7 @@ class Cache {
|
|
|
40
46
|
return this.redis.del(key);
|
|
41
47
|
}
|
|
42
48
|
/**
|
|
43
|
-
* 直接设置缓存 -
|
|
49
|
+
* 直接设置缓存 - 不经过序列化的数据
|
|
44
50
|
* @param key
|
|
45
51
|
* @param value
|
|
46
52
|
* @param ttl 缓存有效时长 (秒),不设置取默认设置
|
|
@@ -54,19 +60,13 @@ class Cache {
|
|
|
54
60
|
/**
|
|
55
61
|
* 缓存对象
|
|
56
62
|
* @param key 缓存key
|
|
57
|
-
* @param value 缓存值,除了 `Buffer`
|
|
63
|
+
* @param value 缓存值,除了 `Buffer` 以外的值会经过序列化
|
|
58
64
|
* @param ttlopt 缓存有效时长 (秒),不设置取默认设置 | 缓存选项
|
|
59
65
|
*/
|
|
60
66
|
async set(key, value, ttlopt) {
|
|
61
|
-
var _a;
|
|
62
67
|
let compressed;
|
|
63
|
-
let data = Buffer.isBuffer(value) ? value :
|
|
64
|
-
const opt = Object.assign({
|
|
65
|
-
ttl: 60,
|
|
66
|
-
compressMinLength: 1024,
|
|
67
|
-
compressStoreRatio: 0.95,
|
|
68
|
-
compressLevel: 1,
|
|
69
|
-
}, (_a = this.option) === null || _a === void 0 ? void 0 : _a.set, typeof ttlopt === 'object' ? ttlopt : undefined);
|
|
68
|
+
let data = Buffer.isBuffer(value) ? value : this.option.serializer.serialize(value);
|
|
69
|
+
const opt = Object.assign({}, this.option.set, typeof ttlopt === 'object' ? ttlopt : undefined);
|
|
70
70
|
if (typeof ttlopt === 'number') {
|
|
71
71
|
opt.ttl = ttlopt;
|
|
72
72
|
}
|
|
@@ -107,116 +107,159 @@ class Cache {
|
|
|
107
107
|
// 解析处理
|
|
108
108
|
if (_opt.parse) {
|
|
109
109
|
_getDebug('[%s] parse', key);
|
|
110
|
-
return
|
|
110
|
+
return this.option.serializer.deserialize(data);
|
|
111
111
|
}
|
|
112
112
|
return new CacheResult(compressed, data);
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
lockGet(key, fetch, opt) {
|
|
116
|
+
const _opt = Object.assign({}, this.option.set, this.option.lockGet, opt);
|
|
117
|
+
return new LockGet(this, key, fetch, _opt).get();
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* 单例执行,在并发情况下保证同一个 key 只会单独执行,防止同时处理
|
|
121
|
+
* @param key 锁key
|
|
122
|
+
* @param run 获得锁时调用
|
|
123
|
+
*/
|
|
124
|
+
async singleRunner(key, run, _opt) {
|
|
125
|
+
const opt = Object.assign({}, this.option.lockGet, _opt);
|
|
126
|
+
const locker = new locker_1.Locker(this.redis, key, opt.lockTimeout);
|
|
127
|
+
const retryTimeout = typeof opt.retryTimeout === 'number' ? opt.retryTimeout : 0;
|
|
128
|
+
const retryDelay = (opt.retryDelay === undefined || opt.retryDelay < 0) ? 500 : opt.retryDelay;
|
|
129
|
+
let retryTime = 0;
|
|
130
|
+
while (true) {
|
|
131
|
+
// 取得锁并执行
|
|
132
|
+
if (await locker.acquire()) {
|
|
133
|
+
try {
|
|
134
|
+
return await run();
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
await locker.release();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// 无法取得锁是否重复尝试
|
|
141
|
+
if (retryTime >= retryTimeout) {
|
|
142
|
+
throw new Error('Unable to acquire lock');
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
retryTime += retryDelay;
|
|
146
|
+
await (0, utils_1.sleep)(retryDelay);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.Cache = Cache;
|
|
152
|
+
class LockGet {
|
|
153
|
+
constructor(cache, key, fetch, opt) {
|
|
154
|
+
this.cache = cache;
|
|
155
|
+
this.key = key;
|
|
156
|
+
this.fetch = fetch;
|
|
157
|
+
this.opt = opt;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* 获取数据并设置到缓存中
|
|
161
|
+
*/
|
|
162
|
+
async fetchAndSet() {
|
|
163
|
+
const obj = await this.fetch();
|
|
118
164
|
// 本地存储
|
|
119
|
-
if (
|
|
120
|
-
|
|
165
|
+
if (this.opt.localStore) {
|
|
166
|
+
this.opt.localStore[this.key] = obj;
|
|
121
167
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
168
|
+
const result = await this.cache.set(this.key, obj, this.opt);
|
|
169
|
+
if (this.opt.parse !== false) {
|
|
170
|
+
return obj;
|
|
171
|
+
}
|
|
172
|
+
return new CacheResult(!this.opt.decompress && Boolean(result.compressed), !this.opt.decompress && result.compressed || Buffer.from(result.data));
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* 预刷新处理
|
|
176
|
+
*/
|
|
177
|
+
async preRefresh(preRefresh) {
|
|
178
|
+
const ttl = await this.cache.ttl(this.key);
|
|
179
|
+
_lockDebug('[%s] preRefresh remain: %d', this.key, ttl);
|
|
180
|
+
if (ttl < preRefresh) {
|
|
181
|
+
_lockDebug('[%s] preRefresh -> fetchAndSet', this.key);
|
|
182
|
+
await this.fetchAndSet();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* 从缓存中取得数据
|
|
187
|
+
*/
|
|
188
|
+
async getCache() {
|
|
189
|
+
// 本地存储
|
|
190
|
+
if (this.opt.localStore && this.key in this.opt.localStore) {
|
|
191
|
+
return this.opt.localStore[this.key];
|
|
192
|
+
}
|
|
193
|
+
// 尝试从 redis 中获取
|
|
194
|
+
const data = await this.cache.get(this.key, this.opt);
|
|
195
|
+
if (data !== undefined) {
|
|
196
|
+
if (!this.locker && this.opt.preRefresh && this.opt.preRefresh > 0) {
|
|
197
|
+
this.preRefresh(this.opt.preRefresh);
|
|
132
198
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const preRefresh = async () => {
|
|
137
|
-
if (opt.preRefresh && opt.preRefresh > 0) {
|
|
138
|
-
const ttl = await this.redis.ttl(key);
|
|
139
|
-
_lockDebug('[%s] preRefresh remain: %d', key, ttl);
|
|
140
|
-
if (ttl < opt.preRefresh) {
|
|
141
|
-
_lockDebug('[%s] preRefresh -> fetchAndSet', key);
|
|
142
|
-
await fetchAndSet();
|
|
143
|
-
}
|
|
199
|
+
// 本地存储
|
|
200
|
+
if (this.opt.localStore && typeof this.opt.localStore === 'object') {
|
|
201
|
+
this.opt.localStore[this.key] = data;
|
|
144
202
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
203
|
+
return data;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
async tryFetch() {
|
|
207
|
+
const retryTimeout = typeof this.opt.retryTimeout === 'number' ? this.opt.retryTimeout : 5000;
|
|
208
|
+
const retryDelay = (this.opt.retryDelay === undefined || this.opt.retryDelay < 0) ? 500 : this.opt.retryDelay;
|
|
209
|
+
let retryTime = 0;
|
|
150
210
|
while (true) {
|
|
151
|
-
if (!
|
|
211
|
+
if (!this.locker) {
|
|
212
|
+
this.locker = new locker_1.Locker(this.cache.redis, `${this.key}.LOCK`, this.opt.lockTimeout);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
152
215
|
// 尝试从 redis 中获取
|
|
153
|
-
const data = await this.
|
|
216
|
+
const data = await this.getCache();
|
|
154
217
|
if (data !== undefined) {
|
|
155
|
-
if (!locker) {
|
|
156
|
-
preRefresh();
|
|
157
|
-
}
|
|
158
|
-
// 本地存储
|
|
159
|
-
if (opt.localStore) {
|
|
160
|
-
opt.localStore[key] = data;
|
|
161
|
-
}
|
|
162
218
|
return data;
|
|
163
219
|
}
|
|
164
220
|
}
|
|
165
|
-
// 已经跳过 redis 获取可以结束强制刷新,进入锁获取,锁获取不成功则代表其他刷新任务已经进行,只要等待获取即可
|
|
166
|
-
refresh = false;
|
|
167
221
|
// 获取锁
|
|
168
|
-
if (
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
if (await locker.acquire()) {
|
|
172
|
-
_lockDebug('[%s] acquire success', key);
|
|
222
|
+
if (await this.locker.acquire()) {
|
|
223
|
+
_lockDebug('[%s] acquire success', this.key);
|
|
173
224
|
try {
|
|
174
|
-
return await fetchAndSet();
|
|
225
|
+
return await this.fetchAndSet();
|
|
175
226
|
}
|
|
176
227
|
finally {
|
|
177
|
-
await locker.release();
|
|
228
|
+
await this.locker.release();
|
|
178
229
|
}
|
|
179
230
|
}
|
|
180
231
|
else {
|
|
232
|
+
// 不等待为 true 不需要重试,说明有其他请求更新数据
|
|
233
|
+
if (this.opt.noWait === true) {
|
|
234
|
+
_lockDebug('[%s] no wait', this.key);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
181
237
|
// 获取锁失败,有其他请求更新数据,等待后重新获取获取数据
|
|
182
|
-
if (
|
|
183
|
-
throw new Error('Unable to acquire lock: ' + key);
|
|
238
|
+
if (retryTime >= retryTimeout) {
|
|
239
|
+
throw new Error('Unable to acquire lock: ' + this.key);
|
|
184
240
|
}
|
|
185
241
|
else {
|
|
186
|
-
|
|
187
|
-
await (0, utils_1.sleep)(
|
|
242
|
+
retryTime += retryDelay;
|
|
243
|
+
await (0, utils_1.sleep)(retryDelay);
|
|
188
244
|
}
|
|
189
245
|
}
|
|
190
246
|
}
|
|
191
247
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
let retryCount = opt.retryCount || 0;
|
|
201
|
-
while (true) {
|
|
202
|
-
// 取得锁并执行
|
|
203
|
-
if (await locker.acquire()) {
|
|
204
|
-
try {
|
|
205
|
-
return await run();
|
|
206
|
-
}
|
|
207
|
-
finally {
|
|
208
|
-
await locker.release();
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
// 无法取得锁是否重复尝试
|
|
212
|
-
if (retryCount <= 0) {
|
|
213
|
-
throw new Error('Unable to acquire lock');
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
retryCount--;
|
|
217
|
-
await (0, utils_1.sleep)(opt.retryDelay || 300);
|
|
248
|
+
async get() {
|
|
249
|
+
// 如果强制刷新则不需要尝试从缓存获取,直接进入锁获取并取得数据
|
|
250
|
+
const refresh = this.opt.refresh || false;
|
|
251
|
+
if (!refresh) {
|
|
252
|
+
// 先尝试从缓存获取
|
|
253
|
+
const data = await this.getCache();
|
|
254
|
+
if (data !== undefined) {
|
|
255
|
+
return data;
|
|
218
256
|
}
|
|
219
257
|
}
|
|
258
|
+
// 不等待为 true 直接返回 undefined
|
|
259
|
+
if (this.opt.noWait === true) {
|
|
260
|
+
this.tryFetch();
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
return this.tryFetch();
|
|
220
264
|
}
|
|
221
265
|
}
|
|
222
|
-
exports.Cache = Cache;
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ exports.Cache = exports.cached = exports.Locker = exports.$cache = exports.getCa
|
|
|
18
18
|
const cache_1 = require("./cache");
|
|
19
19
|
Object.defineProperty(exports, "Cache", { enumerable: true, get: function () { return cache_1.Cache; } });
|
|
20
20
|
const ioredis_1 = require("ioredis");
|
|
21
|
+
const options_1 = require("./options");
|
|
21
22
|
var global_1 = require("./global");
|
|
22
23
|
Object.defineProperty(exports, "getCache", { enumerable: true, get: function () { return global_1.getCache; } });
|
|
23
24
|
Object.defineProperty(exports, "$cache", { enumerable: true, get: function () { return global_1.$cache; } });
|
|
@@ -27,24 +28,13 @@ var locker_1 = require("./locker");
|
|
|
27
28
|
Object.defineProperty(exports, "Locker", { enumerable: true, get: function () { return locker_1.Locker; } });
|
|
28
29
|
var middleware_1 = require("./middleware");
|
|
29
30
|
Object.defineProperty(exports, "cached", { enumerable: true, get: function () { return middleware_1.cached; } });
|
|
30
|
-
/**
|
|
31
|
-
* 默认选项
|
|
32
|
-
*/
|
|
33
|
-
const defaultOption = {
|
|
34
|
-
redis: {
|
|
35
|
-
host: process.env.REDIS_HOST || '127.0.0.1',
|
|
36
|
-
port: parseInt(process.env.REDIS_PORT || '') || 6379,
|
|
37
|
-
password: process.env.REDIS_PASSWORD || '',
|
|
38
|
-
db: parseInt(process.env.REDIS_DB || '') || 0,
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
31
|
/**
|
|
42
32
|
* 安装模块
|
|
43
33
|
* @param option 配置
|
|
44
34
|
*/
|
|
45
35
|
function setup(option) {
|
|
46
36
|
return async function cache(setup) {
|
|
47
|
-
const opt = Object.assign({},
|
|
37
|
+
const opt = Object.assign({}, options_1.defaultSetupOption, option);
|
|
48
38
|
setup.debug('option: %o', opt);
|
|
49
39
|
const redis = opt.redis instanceof ioredis_1.Redis ? opt.redis : new ioredis_1.Redis(opt.redis);
|
|
50
40
|
await redis.ping('check');
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RedisOptions } from "ioredis";
|
|
2
|
+
import type { LockGetOption, ObjectSerializer, SetOption, SetupOption } from "./types";
|
|
3
|
+
export declare const defaultRedisOption: RedisOptions;
|
|
4
|
+
export declare const defaultSetOption: SetOption;
|
|
5
|
+
export declare const defaultLockGetOption: LockGetOption;
|
|
6
|
+
export declare const defaultSerializer: ObjectSerializer;
|
|
7
|
+
export declare const defaultSetupOption: Required<SetupOption>;
|
package/dist/options.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultSetupOption = exports.defaultSerializer = exports.defaultLockGetOption = exports.defaultSetOption = exports.defaultRedisOption = void 0;
|
|
4
|
+
exports.defaultRedisOption = {
|
|
5
|
+
host: process.env.REDIS_HOST || '127.0.0.1',
|
|
6
|
+
port: parseInt(process.env.REDIS_PORT || '') || 6379,
|
|
7
|
+
password: process.env.REDIS_PASSWORD || '',
|
|
8
|
+
db: parseInt(process.env.REDIS_DB || '') || 0,
|
|
9
|
+
};
|
|
10
|
+
exports.defaultSetOption = {
|
|
11
|
+
ttl: 60,
|
|
12
|
+
compressMinLength: 1024,
|
|
13
|
+
compressStoreRatio: 0.95,
|
|
14
|
+
compressLevel: 1,
|
|
15
|
+
};
|
|
16
|
+
exports.defaultLockGetOption = {
|
|
17
|
+
retryTimeout: 5000,
|
|
18
|
+
retryDelay: 500,
|
|
19
|
+
preRefresh: 0,
|
|
20
|
+
refresh: false,
|
|
21
|
+
localStore: undefined,
|
|
22
|
+
};
|
|
23
|
+
exports.defaultSerializer = {
|
|
24
|
+
serialize: (data) => {
|
|
25
|
+
return Buffer.from(JSON.stringify(data));
|
|
26
|
+
},
|
|
27
|
+
deserialize: (data) => {
|
|
28
|
+
return JSON.parse(data.toString());
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
exports.defaultSetupOption = {
|
|
32
|
+
redis: exports.defaultRedisOption,
|
|
33
|
+
set: exports.defaultSetOption,
|
|
34
|
+
lockGet: exports.defaultLockGetOption,
|
|
35
|
+
serializer: exports.defaultSerializer,
|
|
36
|
+
};
|
package/dist/types.d.ts
CHANGED
|
@@ -34,11 +34,18 @@ export interface SetOption {
|
|
|
34
34
|
*/
|
|
35
35
|
compressLevel?: number;
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* 对象序列化
|
|
39
|
+
*/
|
|
40
|
+
export interface ObjectSerializer {
|
|
41
|
+
serialize(data: object): Buffer;
|
|
42
|
+
deserialize(data: Buffer): object;
|
|
43
|
+
}
|
|
37
44
|
export interface SetupOption {
|
|
38
45
|
/**
|
|
39
46
|
* Redis 实例或 Redis 选项
|
|
40
47
|
*/
|
|
41
|
-
redis
|
|
48
|
+
redis?: Redis | RedisOptions;
|
|
42
49
|
/**
|
|
43
50
|
* 默认缓存设置选项
|
|
44
51
|
*/
|
|
@@ -47,13 +54,18 @@ export interface SetupOption {
|
|
|
47
54
|
* 默认锁缓存选项
|
|
48
55
|
*/
|
|
49
56
|
lockGet?: LockGetOption;
|
|
57
|
+
/**
|
|
58
|
+
* 自定义序列化器
|
|
59
|
+
* - 默认为 JSON 序列化
|
|
60
|
+
*/
|
|
61
|
+
serializer?: ObjectSerializer;
|
|
50
62
|
}
|
|
51
63
|
/**
|
|
52
64
|
* 取得缓存选项
|
|
53
65
|
*/
|
|
54
66
|
export interface GetOption {
|
|
55
67
|
/**
|
|
56
|
-
*
|
|
68
|
+
* 是否反序列化数据为对象
|
|
57
69
|
* @default true
|
|
58
70
|
*/
|
|
59
71
|
parse?: boolean;
|
|
@@ -88,15 +100,15 @@ export interface LockOption {
|
|
|
88
100
|
*/
|
|
89
101
|
lockTimeout?: number;
|
|
90
102
|
/**
|
|
91
|
-
*
|
|
103
|
+
* 数据获取重试超时 (毫秒)
|
|
92
104
|
* - 0 不进行重试
|
|
93
|
-
* - lockGet 默认为
|
|
105
|
+
* - lockGet 默认为 5000
|
|
94
106
|
* - singleRunner 默认为 0
|
|
95
107
|
*/
|
|
96
|
-
|
|
108
|
+
retryTimeout?: number;
|
|
97
109
|
/**
|
|
98
|
-
*
|
|
99
|
-
* @default
|
|
110
|
+
* 数据获取重试间隔 (毫秒)
|
|
111
|
+
* @default 500
|
|
100
112
|
*/
|
|
101
113
|
retryDelay?: number;
|
|
102
114
|
}
|
|
@@ -126,4 +138,11 @@ export interface LockGetOption extends GetOption, SetOption, LockOption {
|
|
|
126
138
|
localStore?: {
|
|
127
139
|
[key: string]: any;
|
|
128
140
|
};
|
|
141
|
+
/**
|
|
142
|
+
* 不等待
|
|
143
|
+
* - 当缓存不存在时直接返回 `undefined`,之后使用 `fetch` 取得数据并设置缓存
|
|
144
|
+
* - 应用场景: 某些数据并不参与业务逻辑又比较耗时,当 `fetch` 处理时间过长的情况下可能会造成请求超时,使用 `wait: false` 可以跳过等待
|
|
145
|
+
* @default false
|
|
146
|
+
*/
|
|
147
|
+
noWait?: boolean;
|
|
129
148
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenweb/cache",
|
|
3
3
|
"packageManager": "yarn@4.0.2",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.6.0",
|
|
5
5
|
"description": "Zenweb Cache module",
|
|
6
6
|
"exports": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"scripts": {
|
|
12
12
|
"vscode": "yarn dlx @yarnpkg/sdks vscode",
|
|
13
13
|
"build": "rimraf dist && tsc",
|
|
14
|
-
"
|
|
14
|
+
"prepack": "yarn run build",
|
|
15
15
|
"test": "ts-mocha -p tsconfig.json test/**/*.test.ts",
|
|
16
16
|
"dev": "cd example && cross-env DEBUG=\\* NODE_ENV=development ts-node app"
|
|
17
17
|
},
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"@types/node": "^20.10.6",
|
|
37
37
|
"cross-env": "^7.0.3",
|
|
38
38
|
"mocha": "^10.2.0",
|
|
39
|
+
"msgpackr": "^1.11.0",
|
|
39
40
|
"rimraf": "^4.3.1",
|
|
40
41
|
"ts-mocha": "^10.0.0",
|
|
41
42
|
"ts-node": "^10.9.1",
|