baja-lite 1.8.12 → 1.8.13
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/cache.d.ts +4 -0
- package/cache.js +26 -9
- package/package.json +1 -1
package/cache.d.ts
CHANGED
|
@@ -31,6 +31,8 @@ export declare function excuteWithLock<T>(config: {
|
|
|
31
31
|
lockRetryInterval?: number;
|
|
32
32
|
/** 当设置了lockWait=true时,等待多少【毫秒】即视为超时,放弃本次访问?默认:永不放弃 */
|
|
33
33
|
lockMaxWaitTime?: number;
|
|
34
|
+
/** 最大重试次数。默认 5。超过后抛出异常。 */
|
|
35
|
+
lockMaxRetries?: number;
|
|
34
36
|
/** 错误信息 */
|
|
35
37
|
errorMessage?: string;
|
|
36
38
|
/** 允许的并发数,默认:1 */
|
|
@@ -53,6 +55,8 @@ export declare function MethodLock<T = any>(config: {
|
|
|
53
55
|
lockRetryInterval?: number;
|
|
54
56
|
/** 当设置了lockWait=true时,等待多少【毫秒】即视为超时,放弃本次访问?默认永不放弃 */
|
|
55
57
|
lockMaxWaitTime?: number;
|
|
58
|
+
/** 最大重试次数。默认 5。超过后抛出异常。 */
|
|
59
|
+
lockMaxRetries?: number;
|
|
56
60
|
/** 错误信息 */
|
|
57
61
|
errorMessage?: string;
|
|
58
62
|
/** 允许的并发数,默认=1 */
|
package/cache.js
CHANGED
|
@@ -129,18 +129,23 @@ export async function GetRedisLock(key, lockMaxActive) {
|
|
|
129
129
|
export async function excuteWithLock(config, fn__) {
|
|
130
130
|
const key = `[lock]${typeof config.key === 'function' ? config.key() : config.key}`;
|
|
131
131
|
const db = getRedisDB();
|
|
132
|
+
const maxRetries = config.lockMaxRetries ?? 5;
|
|
133
|
+
let retries = 0;
|
|
132
134
|
let wait_time = 0;
|
|
133
135
|
const fn = async () => {
|
|
134
136
|
const lock = await GetRedisLock(key, config.lockMaxActive);
|
|
135
137
|
if (lock === false) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
+
retries++;
|
|
139
|
+
const timeOk = (config.lockMaxWaitTime ?? 0) === 0 || (wait_time + (config.lockRetryInterval ?? 100)) <= (config.lockMaxWaitTime ?? 0);
|
|
140
|
+
const retryOk = retries < maxRetries;
|
|
141
|
+
if (config.lockWait !== false && timeOk && retryOk) {
|
|
142
|
+
globalThis[_LoggerService].debugCategory?.('sql', `get lock ${key} fail, retry ${retries}/${maxRetries} after ${config.lockRetryInterval ?? 100}ms...`);
|
|
138
143
|
await sleep(config.lockRetryInterval ?? 100);
|
|
139
144
|
wait_time += (config.lockRetryInterval ?? 100);
|
|
140
145
|
return await fn();
|
|
141
146
|
}
|
|
142
147
|
else {
|
|
143
|
-
globalThis[_LoggerService].debugCategory?.('sql', `get lock ${key} fail`);
|
|
148
|
+
globalThis[_LoggerService].debugCategory?.('sql', `get lock ${key} fail after ${retries} retries`);
|
|
144
149
|
throw new Error(config.errorMessage || `get lock fail: ${key}`);
|
|
145
150
|
}
|
|
146
151
|
}
|
|
@@ -641,12 +646,24 @@ export async function excuteWithCache(config, fn) {
|
|
|
641
646
|
}
|
|
642
647
|
}
|
|
643
648
|
if (Date.now() - waitStart > SINGLEFLIGHT_MAX_WAIT_MS) {
|
|
644
|
-
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
649
|
+
// 超时后重新抢锁(新一轮领导选举),而非直接跑 fn 导致雪崩
|
|
650
|
+
const retry = await db.set(sfKey, '1', 'PX', SINGLEFLIGHT_LOCK_TTL_MS, 'NX');
|
|
651
|
+
if (retry === 'OK') {
|
|
652
|
+
cacheLog(`${key}: wait timed out, re-elected as leader`);
|
|
653
|
+
try {
|
|
654
|
+
const result = await fn();
|
|
655
|
+
await setMethodCache({ key, ...setOpts, result }, devid);
|
|
656
|
+
void onCacheUpdated?.call(ctx, result, ...callArgs);
|
|
657
|
+
return result;
|
|
658
|
+
}
|
|
659
|
+
finally {
|
|
660
|
+
try {
|
|
661
|
+
await db.del(sfKey);
|
|
662
|
+
}
|
|
663
|
+
catch { /* TTL 兜底 */ }
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
// 没抢到说明又有别人接手了,继续等
|
|
650
667
|
}
|
|
651
668
|
}
|
|
652
669
|
}
|