@abtnode/db-cache 1.16.47-beta-20250730-070104-87a128a5 → 1.16.47-beta-20250731-014139-e860268f

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/index.cjs CHANGED
@@ -166,48 +166,94 @@ __publicField$4(_RedisAdapter, "clients", /* @__PURE__ */ new Map());
166
166
  __publicField$4(_RedisAdapter, "initPromises", /* @__PURE__ */ new Map());
167
167
  let RedisAdapter = _RedisAdapter;
168
168
 
169
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
170
+ async function withRetry(fn, {
171
+ max = 15,
172
+ backoffBase = 200,
173
+ backoffExponent = 1.1,
174
+ backoffJitter = 100,
175
+ needRetry = () => true
176
+ // eslint-disable-next-line @typescript-eslint/comma-dangle
177
+ } = {}) {
178
+ let attempt = 0;
179
+ while (true) {
180
+ try {
181
+ return await fn();
182
+ } catch (err) {
183
+ if (!needRetry(err) || ++attempt > max) {
184
+ throw err;
185
+ }
186
+ const exp = backoffExponent ** (attempt - 1);
187
+ const expDelay = backoffBase * exp;
188
+ const jitter = Math.random() * backoffJitter;
189
+ const waitTime = Math.floor(expDelay + jitter);
190
+ await sleep(waitTime);
191
+ }
192
+ }
193
+ }
194
+
169
195
  var __defProp$3 = Object.defineProperty;
170
196
  var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
171
197
  var __publicField$3 = (obj, key, value) => {
172
198
  __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
173
199
  return value;
174
200
  };
175
- const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
201
+ const retryOptions = {
202
+ needRetry: (err) => err.message?.includes("SQLITE_BUSY")
203
+ };
204
+ const dbRun = (db, sql, params) => {
205
+ return withRetry(() => {
206
+ return new Promise((res, rej) => {
207
+ db.run(sql, params, (err) => err ? rej(err) : res());
208
+ });
209
+ }, retryOptions);
210
+ };
211
+ const dbExec = (db, sql) => {
212
+ return withRetry(() => {
213
+ return new Promise((res, rej) => {
214
+ db.exec(sql, (err) => err ? rej(err) : res());
215
+ });
216
+ }, retryOptions);
217
+ };
218
+ const dbGet = (db, sql, params) => {
219
+ return withRetry(() => {
220
+ return new Promise((res, rej) => {
221
+ db.get(sql, params, (err, result) => err ? rej(err) : res(result));
222
+ });
223
+ }, retryOptions);
224
+ };
176
225
  async function initSqliteWithRetry(db) {
177
- const sql = `
178
- PRAGMA journal_mode = WAL;
179
- PRAGMA synchronous = OFF;
180
- PRAGMA busy_timeout = 20000;
181
- PRAGMA wal_autocheckpoint = 10000;
182
- `;
183
- const maxRetries = 10;
184
- const delayMs = 2e3;
185
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
186
- try {
187
- await new Promise((resolve, reject) => {
188
- db.exec(sql, (err) => {
189
- if (err)
190
- reject(err);
191
- else
192
- resolve();
193
- });
194
- });
195
- return;
196
- } catch (err) {
197
- if (attempt < maxRetries) {
198
- await new Promise((resolve) => setTimeout(resolve, delayMs));
199
- } else {
200
- throw new Error(`SQLite init failed, retried ${maxRetries} times: ${err}`);
201
- }
202
- }
226
+ db.configure("busyTimeout", 5e3);
227
+ try {
228
+ await dbExec(
229
+ db,
230
+ `
231
+ PRAGMA journal_mode = WAL;
232
+ PRAGMA synchronous = normal;
233
+ PRAGMA wal_autocheckpoint = 5000;
234
+ PRAGMA busy_timeout = 5000;
235
+ `
236
+ );
237
+ await dbRun(
238
+ db,
239
+ `
240
+ CREATE TABLE IF NOT EXISTS kvcache (
241
+ key TEXT NOT NULL,
242
+ subKey TEXT NOT NULL,
243
+ value TEXT NOT NULL,
244
+ expiresAt INTEGER,
245
+ PRIMARY KEY (key, subKey)
246
+ )
247
+ `
248
+ );
249
+ } catch (err) {
250
+ throw new Error(`SQLite init failed: ${err}`);
203
251
  }
204
252
  }
205
253
  const _SqliteAdapter = class _SqliteAdapter {
206
254
  constructor() {
207
255
  __publicField$3(this, "opts", null);
208
256
  __publicField$3(this, "prefix", "");
209
- __publicField$3(this, "sqliteBusyRetryCount", 0);
210
- __publicField$3(this, "sqliteBusyRetryGroupCount", 0);
211
257
  __publicField$3(this, "defaultTtl", 1e3 * 60 * 60);
212
258
  __publicField$3(this, "cleanupInterval", 5 * 60 * 1e3);
213
259
  __publicField$3(this, "dbPath", "");
@@ -235,28 +281,6 @@ const _SqliteAdapter = class _SqliteAdapter {
235
281
  }
236
282
  const db = new sqlite3__default.Database(this.dbPath);
237
283
  await initSqliteWithRetry(db);
238
- await new Promise(
239
- (res, rej) => db.run(
240
- `
241
- CREATE TABLE IF NOT EXISTS kvcache (
242
- key TEXT NOT NULL,
243
- subKey TEXT NOT NULL,
244
- value TEXT NOT NULL,
245
- expiresAt INTEGER,
246
- PRIMARY KEY (key, subKey)
247
- )
248
- `,
249
- (err) => err ? rej(err) : res()
250
- )
251
- );
252
- await new Promise(
253
- (res, rej) => db.run(
254
- `
255
- PRAGMA shrink_memory;
256
- `,
257
- (err) => err ? rej(err) : res()
258
- )
259
- );
260
284
  _SqliteAdapter.clients.set(this.dbPath, db);
261
285
  _SqliteAdapter.cleanupTimers.set(
262
286
  this.dbPath,
@@ -315,51 +339,28 @@ const _SqliteAdapter = class _SqliteAdapter {
315
339
  if (exists)
316
340
  return false;
317
341
  }
318
- try {
319
- await new Promise((res, rej) => {
320
- client.run(
321
- `
322
- INSERT INTO kvcache (key, subKey, value, expiresAt)
323
- VALUES (?, ?, ?, ?)
324
- ON CONFLICT(key, subKey) DO UPDATE SET
325
- value = excluded.value,
326
- expiresAt = excluded.expiresAt
327
- `,
328
- [storageKey, subKey, this.serialize(value), expiresAt],
329
- (err) => err ? rej(err) : res()
330
- );
331
- });
332
- } catch (error) {
333
- if (error.message?.includes("SQLITE_BUSY")) {
334
- if (this.sqliteBusyRetryCount > 10) {
335
- this.sqliteBusyRetryCount = 0;
336
- throw error;
337
- }
338
- this.sqliteBusyRetryCount++;
339
- await sleep(2e3);
340
- const out = await this.set(key, value, opts);
341
- this.sqliteBusyRetryCount = 0;
342
- return out;
343
- }
344
- throw error;
345
- }
342
+ await dbRun(
343
+ client,
344
+ `
345
+ INSERT INTO kvcache (key, subKey, value, expiresAt)
346
+ VALUES (?, ?, ?, ?)
347
+ ON CONFLICT(key, subKey) DO UPDATE SET
348
+ value = excluded.value,
349
+ expiresAt = excluded.expiresAt
350
+ `,
351
+ [storageKey, subKey, this.serialize(value), expiresAt]
352
+ );
346
353
  return true;
347
354
  }
348
355
  async get(key) {
349
356
  const client = this.getClient();
350
357
  const storageKey = this.prefixKey(key);
351
358
  const subKey = "";
352
- const row = await new Promise((res, rej) => {
353
- client.get(
354
- 'SELECT value, "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
355
- [storageKey, subKey],
356
- (err, result) => {
357
- if (err)
358
- return rej(err);
359
- return res(result);
360
- }
361
- );
362
- });
359
+ const row = await dbGet(
360
+ client,
361
+ 'SELECT value, "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
362
+ [storageKey, subKey]
363
+ );
363
364
  if (!row)
364
365
  return null;
365
366
  if (row.expiresAt !== null && Date.now() > row.expiresAt) {
@@ -371,22 +372,17 @@ const _SqliteAdapter = class _SqliteAdapter {
371
372
  async del(key) {
372
373
  const client = this.getClient();
373
374
  const storageKey = this.prefixKey(key);
374
- await new Promise((res, rej) => {
375
- client.run("DELETE FROM kvcache WHERE key = ?", [storageKey], (err) => err ? rej(err) : res());
376
- });
375
+ await dbRun(client, "DELETE FROM kvcache WHERE key = ?", [storageKey]);
377
376
  }
378
377
  async has(key) {
379
378
  const client = this.getClient();
380
379
  const storageKey = this.prefixKey(key);
381
380
  const subKey = "";
382
- const row = await new Promise((res, rej) => {
383
- client.get(
384
- 'SELECT "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
385
- [storageKey, subKey],
386
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
387
- (err, result) => err ? rej(err) : res(result)
388
- );
389
- });
381
+ const row = await dbGet(
382
+ client,
383
+ 'SELECT "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
384
+ [storageKey, subKey]
385
+ );
390
386
  if (!row)
391
387
  return false;
392
388
  if (row.expiresAt !== null && Date.now() > row.expiresAt) {
@@ -405,49 +401,26 @@ const _SqliteAdapter = class _SqliteAdapter {
405
401
  if (exists)
406
402
  return;
407
403
  }
408
- try {
409
- await new Promise((res, rej) => {
410
- client.run(
411
- `
412
- INSERT INTO kvcache (key, subKey, value, expiresAt)
413
- VALUES (?, ?, ?, ?)
414
- ON CONFLICT(key, subKey) DO UPDATE SET
415
- value = excluded.value,
416
- expiresAt = excluded.expiresAt
417
- `,
418
- [storageKey, subKey, this.serialize(value), expiresAt],
419
- (err) => err ? rej(err) : res()
420
- );
421
- });
422
- } catch (error) {
423
- if (error.message?.includes("SQLITE_BUSY")) {
424
- if (this.sqliteBusyRetryGroupCount > 10) {
425
- this.sqliteBusyRetryGroupCount = 0;
426
- throw error;
427
- }
428
- this.sqliteBusyRetryGroupCount++;
429
- await sleep(2e3);
430
- await this.groupSet(key, subKey, value, opts);
431
- this.sqliteBusyRetryGroupCount = 0;
432
- return;
433
- }
434
- throw error;
435
- }
404
+ await dbRun(
405
+ client,
406
+ `
407
+ INSERT INTO kvcache (key, subKey, value, expiresAt)
408
+ VALUES (?, ?, ?, ?)
409
+ ON CONFLICT(key, subKey) DO UPDATE SET
410
+ value = excluded.value,
411
+ expiresAt = excluded.expiresAt
412
+ `,
413
+ [storageKey, subKey, this.serialize(value), expiresAt]
414
+ );
436
415
  }
437
416
  async groupGet(key, subKey) {
438
417
  const client = this.getClient();
439
418
  const storageKey = this.prefixKey(key);
440
- const row = await new Promise((res, rej) => {
441
- client.get(
442
- 'SELECT value, "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
443
- [storageKey, subKey],
444
- (err, result) => {
445
- if (err)
446
- return rej(err);
447
- return res(result);
448
- }
449
- );
450
- });
419
+ const row = await dbGet(
420
+ client,
421
+ 'SELECT value, "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
422
+ [storageKey, subKey]
423
+ );
451
424
  if (!row)
452
425
  return null;
453
426
  if (row.expiresAt !== null && Date.now() > row.expiresAt) {
@@ -459,14 +432,11 @@ const _SqliteAdapter = class _SqliteAdapter {
459
432
  async groupHas(key, subKey) {
460
433
  const client = this.getClient();
461
434
  const storageKey = this.prefixKey(key);
462
- const row = await new Promise((res, rej) => {
463
- client.get(
464
- 'SELECT "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
465
- [storageKey, subKey],
466
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
467
- (err, result) => err ? rej(err) : res(result)
468
- );
469
- });
435
+ const row = await dbGet(
436
+ client,
437
+ 'SELECT "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
438
+ [storageKey, subKey]
439
+ );
470
440
  if (!row)
471
441
  return false;
472
442
  if (row.expiresAt !== null && Date.now() > row.expiresAt) {
@@ -478,13 +448,7 @@ const _SqliteAdapter = class _SqliteAdapter {
478
448
  async groupDel(key, subKey) {
479
449
  const client = this.getClient();
480
450
  const storageKey = this.prefixKey(key);
481
- await new Promise((res, rej) => {
482
- client.run(
483
- "DELETE FROM kvcache WHERE key = ? AND subKey = ?",
484
- [storageKey, subKey],
485
- (err) => err ? rej(err) : res()
486
- );
487
- });
451
+ return dbRun(client, "DELETE FROM kvcache WHERE key = ? AND subKey = ?", [storageKey, subKey]);
488
452
  }
489
453
  async close() {
490
454
  if (this.dbPath) {
@@ -876,3 +840,4 @@ const getAbtNodeRedisAndSQLiteUrl = () => {
876
840
 
877
841
  exports.DBCache = LockDBCache;
878
842
  exports.getAbtNodeRedisAndSQLiteUrl = getAbtNodeRedisAndSQLiteUrl;
843
+ exports.withRetry = withRetry;
package/dist/index.d.cts CHANGED
@@ -120,9 +120,23 @@ declare class LockDBCache extends SingleFlightDBCache {
120
120
  private _formatLockKey;
121
121
  }
122
122
 
123
+ interface WithRetryOptions {
124
+ /** 最大重试次数 */
125
+ max?: number;
126
+ /** 初始退避时长,单位 ms */
127
+ backoffBase?: number;
128
+ /** 每次重试时的指数倍数 */
129
+ backoffExponent?: number;
130
+ /** 抖动范围,0~backoffJitter 毫秒 */
131
+ backoffJitter?: number;
132
+ /** 判断是否需要重试的函数 */
133
+ needRetry?: (err: any) => boolean;
134
+ }
135
+ declare function withRetry<T>(fn: () => Promise<T>, { max, backoffBase, backoffExponent, backoffJitter, needRetry, }?: WithRetryOptions): Promise<T>;
136
+
123
137
  declare const getAbtNodeRedisAndSQLiteUrl: () => {
124
138
  redisUrl: string | undefined;
125
139
  sqlitePath: string | undefined;
126
140
  };
127
141
 
128
- export { type BaseDBCacheOptions, LockDBCache as DBCache, type IDBAdapter, getAbtNodeRedisAndSQLiteUrl };
142
+ export { type BaseDBCacheOptions, LockDBCache as DBCache, type IDBAdapter, getAbtNodeRedisAndSQLiteUrl, withRetry };
package/dist/index.d.mts CHANGED
@@ -120,9 +120,23 @@ declare class LockDBCache extends SingleFlightDBCache {
120
120
  private _formatLockKey;
121
121
  }
122
122
 
123
+ interface WithRetryOptions {
124
+ /** 最大重试次数 */
125
+ max?: number;
126
+ /** 初始退避时长,单位 ms */
127
+ backoffBase?: number;
128
+ /** 每次重试时的指数倍数 */
129
+ backoffExponent?: number;
130
+ /** 抖动范围,0~backoffJitter 毫秒 */
131
+ backoffJitter?: number;
132
+ /** 判断是否需要重试的函数 */
133
+ needRetry?: (err: any) => boolean;
134
+ }
135
+ declare function withRetry<T>(fn: () => Promise<T>, { max, backoffBase, backoffExponent, backoffJitter, needRetry, }?: WithRetryOptions): Promise<T>;
136
+
123
137
  declare const getAbtNodeRedisAndSQLiteUrl: () => {
124
138
  redisUrl: string | undefined;
125
139
  sqlitePath: string | undefined;
126
140
  };
127
141
 
128
- export { type BaseDBCacheOptions, LockDBCache as DBCache, type IDBAdapter, getAbtNodeRedisAndSQLiteUrl };
142
+ export { type BaseDBCacheOptions, LockDBCache as DBCache, type IDBAdapter, getAbtNodeRedisAndSQLiteUrl, withRetry };
package/dist/index.d.ts CHANGED
@@ -120,9 +120,23 @@ declare class LockDBCache extends SingleFlightDBCache {
120
120
  private _formatLockKey;
121
121
  }
122
122
 
123
+ interface WithRetryOptions {
124
+ /** 最大重试次数 */
125
+ max?: number;
126
+ /** 初始退避时长,单位 ms */
127
+ backoffBase?: number;
128
+ /** 每次重试时的指数倍数 */
129
+ backoffExponent?: number;
130
+ /** 抖动范围,0~backoffJitter 毫秒 */
131
+ backoffJitter?: number;
132
+ /** 判断是否需要重试的函数 */
133
+ needRetry?: (err: any) => boolean;
134
+ }
135
+ declare function withRetry<T>(fn: () => Promise<T>, { max, backoffBase, backoffExponent, backoffJitter, needRetry, }?: WithRetryOptions): Promise<T>;
136
+
123
137
  declare const getAbtNodeRedisAndSQLiteUrl: () => {
124
138
  redisUrl: string | undefined;
125
139
  sqlitePath: string | undefined;
126
140
  };
127
141
 
128
- export { type BaseDBCacheOptions, LockDBCache as DBCache, type IDBAdapter, getAbtNodeRedisAndSQLiteUrl };
142
+ export { type BaseDBCacheOptions, LockDBCache as DBCache, type IDBAdapter, getAbtNodeRedisAndSQLiteUrl, withRetry };
package/dist/index.mjs CHANGED
@@ -146,48 +146,94 @@ __publicField$4(_RedisAdapter, "clients", /* @__PURE__ */ new Map());
146
146
  __publicField$4(_RedisAdapter, "initPromises", /* @__PURE__ */ new Map());
147
147
  let RedisAdapter = _RedisAdapter;
148
148
 
149
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
150
+ async function withRetry(fn, {
151
+ max = 15,
152
+ backoffBase = 200,
153
+ backoffExponent = 1.1,
154
+ backoffJitter = 100,
155
+ needRetry = () => true
156
+ // eslint-disable-next-line @typescript-eslint/comma-dangle
157
+ } = {}) {
158
+ let attempt = 0;
159
+ while (true) {
160
+ try {
161
+ return await fn();
162
+ } catch (err) {
163
+ if (!needRetry(err) || ++attempt > max) {
164
+ throw err;
165
+ }
166
+ const exp = backoffExponent ** (attempt - 1);
167
+ const expDelay = backoffBase * exp;
168
+ const jitter = Math.random() * backoffJitter;
169
+ const waitTime = Math.floor(expDelay + jitter);
170
+ await sleep(waitTime);
171
+ }
172
+ }
173
+ }
174
+
149
175
  var __defProp$3 = Object.defineProperty;
150
176
  var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
151
177
  var __publicField$3 = (obj, key, value) => {
152
178
  __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
153
179
  return value;
154
180
  };
155
- const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
181
+ const retryOptions = {
182
+ needRetry: (err) => err.message?.includes("SQLITE_BUSY")
183
+ };
184
+ const dbRun = (db, sql, params) => {
185
+ return withRetry(() => {
186
+ return new Promise((res, rej) => {
187
+ db.run(sql, params, (err) => err ? rej(err) : res());
188
+ });
189
+ }, retryOptions);
190
+ };
191
+ const dbExec = (db, sql) => {
192
+ return withRetry(() => {
193
+ return new Promise((res, rej) => {
194
+ db.exec(sql, (err) => err ? rej(err) : res());
195
+ });
196
+ }, retryOptions);
197
+ };
198
+ const dbGet = (db, sql, params) => {
199
+ return withRetry(() => {
200
+ return new Promise((res, rej) => {
201
+ db.get(sql, params, (err, result) => err ? rej(err) : res(result));
202
+ });
203
+ }, retryOptions);
204
+ };
156
205
  async function initSqliteWithRetry(db) {
157
- const sql = `
158
- PRAGMA journal_mode = WAL;
159
- PRAGMA synchronous = OFF;
160
- PRAGMA busy_timeout = 20000;
161
- PRAGMA wal_autocheckpoint = 10000;
162
- `;
163
- const maxRetries = 10;
164
- const delayMs = 2e3;
165
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
166
- try {
167
- await new Promise((resolve, reject) => {
168
- db.exec(sql, (err) => {
169
- if (err)
170
- reject(err);
171
- else
172
- resolve();
173
- });
174
- });
175
- return;
176
- } catch (err) {
177
- if (attempt < maxRetries) {
178
- await new Promise((resolve) => setTimeout(resolve, delayMs));
179
- } else {
180
- throw new Error(`SQLite init failed, retried ${maxRetries} times: ${err}`);
181
- }
182
- }
206
+ db.configure("busyTimeout", 5e3);
207
+ try {
208
+ await dbExec(
209
+ db,
210
+ `
211
+ PRAGMA journal_mode = WAL;
212
+ PRAGMA synchronous = normal;
213
+ PRAGMA wal_autocheckpoint = 5000;
214
+ PRAGMA busy_timeout = 5000;
215
+ `
216
+ );
217
+ await dbRun(
218
+ db,
219
+ `
220
+ CREATE TABLE IF NOT EXISTS kvcache (
221
+ key TEXT NOT NULL,
222
+ subKey TEXT NOT NULL,
223
+ value TEXT NOT NULL,
224
+ expiresAt INTEGER,
225
+ PRIMARY KEY (key, subKey)
226
+ )
227
+ `
228
+ );
229
+ } catch (err) {
230
+ throw new Error(`SQLite init failed: ${err}`);
183
231
  }
184
232
  }
185
233
  const _SqliteAdapter = class _SqliteAdapter {
186
234
  constructor() {
187
235
  __publicField$3(this, "opts", null);
188
236
  __publicField$3(this, "prefix", "");
189
- __publicField$3(this, "sqliteBusyRetryCount", 0);
190
- __publicField$3(this, "sqliteBusyRetryGroupCount", 0);
191
237
  __publicField$3(this, "defaultTtl", 1e3 * 60 * 60);
192
238
  __publicField$3(this, "cleanupInterval", 5 * 60 * 1e3);
193
239
  __publicField$3(this, "dbPath", "");
@@ -215,28 +261,6 @@ const _SqliteAdapter = class _SqliteAdapter {
215
261
  }
216
262
  const db = new sqlite3.Database(this.dbPath);
217
263
  await initSqliteWithRetry(db);
218
- await new Promise(
219
- (res, rej) => db.run(
220
- `
221
- CREATE TABLE IF NOT EXISTS kvcache (
222
- key TEXT NOT NULL,
223
- subKey TEXT NOT NULL,
224
- value TEXT NOT NULL,
225
- expiresAt INTEGER,
226
- PRIMARY KEY (key, subKey)
227
- )
228
- `,
229
- (err) => err ? rej(err) : res()
230
- )
231
- );
232
- await new Promise(
233
- (res, rej) => db.run(
234
- `
235
- PRAGMA shrink_memory;
236
- `,
237
- (err) => err ? rej(err) : res()
238
- )
239
- );
240
264
  _SqliteAdapter.clients.set(this.dbPath, db);
241
265
  _SqliteAdapter.cleanupTimers.set(
242
266
  this.dbPath,
@@ -295,51 +319,28 @@ const _SqliteAdapter = class _SqliteAdapter {
295
319
  if (exists)
296
320
  return false;
297
321
  }
298
- try {
299
- await new Promise((res, rej) => {
300
- client.run(
301
- `
302
- INSERT INTO kvcache (key, subKey, value, expiresAt)
303
- VALUES (?, ?, ?, ?)
304
- ON CONFLICT(key, subKey) DO UPDATE SET
305
- value = excluded.value,
306
- expiresAt = excluded.expiresAt
307
- `,
308
- [storageKey, subKey, this.serialize(value), expiresAt],
309
- (err) => err ? rej(err) : res()
310
- );
311
- });
312
- } catch (error) {
313
- if (error.message?.includes("SQLITE_BUSY")) {
314
- if (this.sqliteBusyRetryCount > 10) {
315
- this.sqliteBusyRetryCount = 0;
316
- throw error;
317
- }
318
- this.sqliteBusyRetryCount++;
319
- await sleep(2e3);
320
- const out = await this.set(key, value, opts);
321
- this.sqliteBusyRetryCount = 0;
322
- return out;
323
- }
324
- throw error;
325
- }
322
+ await dbRun(
323
+ client,
324
+ `
325
+ INSERT INTO kvcache (key, subKey, value, expiresAt)
326
+ VALUES (?, ?, ?, ?)
327
+ ON CONFLICT(key, subKey) DO UPDATE SET
328
+ value = excluded.value,
329
+ expiresAt = excluded.expiresAt
330
+ `,
331
+ [storageKey, subKey, this.serialize(value), expiresAt]
332
+ );
326
333
  return true;
327
334
  }
328
335
  async get(key) {
329
336
  const client = this.getClient();
330
337
  const storageKey = this.prefixKey(key);
331
338
  const subKey = "";
332
- const row = await new Promise((res, rej) => {
333
- client.get(
334
- 'SELECT value, "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
335
- [storageKey, subKey],
336
- (err, result) => {
337
- if (err)
338
- return rej(err);
339
- return res(result);
340
- }
341
- );
342
- });
339
+ const row = await dbGet(
340
+ client,
341
+ 'SELECT value, "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
342
+ [storageKey, subKey]
343
+ );
343
344
  if (!row)
344
345
  return null;
345
346
  if (row.expiresAt !== null && Date.now() > row.expiresAt) {
@@ -351,22 +352,17 @@ const _SqliteAdapter = class _SqliteAdapter {
351
352
  async del(key) {
352
353
  const client = this.getClient();
353
354
  const storageKey = this.prefixKey(key);
354
- await new Promise((res, rej) => {
355
- client.run("DELETE FROM kvcache WHERE key = ?", [storageKey], (err) => err ? rej(err) : res());
356
- });
355
+ await dbRun(client, "DELETE FROM kvcache WHERE key = ?", [storageKey]);
357
356
  }
358
357
  async has(key) {
359
358
  const client = this.getClient();
360
359
  const storageKey = this.prefixKey(key);
361
360
  const subKey = "";
362
- const row = await new Promise((res, rej) => {
363
- client.get(
364
- 'SELECT "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
365
- [storageKey, subKey],
366
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
367
- (err, result) => err ? rej(err) : res(result)
368
- );
369
- });
361
+ const row = await dbGet(
362
+ client,
363
+ 'SELECT "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
364
+ [storageKey, subKey]
365
+ );
370
366
  if (!row)
371
367
  return false;
372
368
  if (row.expiresAt !== null && Date.now() > row.expiresAt) {
@@ -385,49 +381,26 @@ const _SqliteAdapter = class _SqliteAdapter {
385
381
  if (exists)
386
382
  return;
387
383
  }
388
- try {
389
- await new Promise((res, rej) => {
390
- client.run(
391
- `
392
- INSERT INTO kvcache (key, subKey, value, expiresAt)
393
- VALUES (?, ?, ?, ?)
394
- ON CONFLICT(key, subKey) DO UPDATE SET
395
- value = excluded.value,
396
- expiresAt = excluded.expiresAt
397
- `,
398
- [storageKey, subKey, this.serialize(value), expiresAt],
399
- (err) => err ? rej(err) : res()
400
- );
401
- });
402
- } catch (error) {
403
- if (error.message?.includes("SQLITE_BUSY")) {
404
- if (this.sqliteBusyRetryGroupCount > 10) {
405
- this.sqliteBusyRetryGroupCount = 0;
406
- throw error;
407
- }
408
- this.sqliteBusyRetryGroupCount++;
409
- await sleep(2e3);
410
- await this.groupSet(key, subKey, value, opts);
411
- this.sqliteBusyRetryGroupCount = 0;
412
- return;
413
- }
414
- throw error;
415
- }
384
+ await dbRun(
385
+ client,
386
+ `
387
+ INSERT INTO kvcache (key, subKey, value, expiresAt)
388
+ VALUES (?, ?, ?, ?)
389
+ ON CONFLICT(key, subKey) DO UPDATE SET
390
+ value = excluded.value,
391
+ expiresAt = excluded.expiresAt
392
+ `,
393
+ [storageKey, subKey, this.serialize(value), expiresAt]
394
+ );
416
395
  }
417
396
  async groupGet(key, subKey) {
418
397
  const client = this.getClient();
419
398
  const storageKey = this.prefixKey(key);
420
- const row = await new Promise((res, rej) => {
421
- client.get(
422
- 'SELECT value, "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
423
- [storageKey, subKey],
424
- (err, result) => {
425
- if (err)
426
- return rej(err);
427
- return res(result);
428
- }
429
- );
430
- });
399
+ const row = await dbGet(
400
+ client,
401
+ 'SELECT value, "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
402
+ [storageKey, subKey]
403
+ );
431
404
  if (!row)
432
405
  return null;
433
406
  if (row.expiresAt !== null && Date.now() > row.expiresAt) {
@@ -439,14 +412,11 @@ const _SqliteAdapter = class _SqliteAdapter {
439
412
  async groupHas(key, subKey) {
440
413
  const client = this.getClient();
441
414
  const storageKey = this.prefixKey(key);
442
- const row = await new Promise((res, rej) => {
443
- client.get(
444
- 'SELECT "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
445
- [storageKey, subKey],
446
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
447
- (err, result) => err ? rej(err) : res(result)
448
- );
449
- });
415
+ const row = await dbGet(
416
+ client,
417
+ 'SELECT "expiresAt" FROM kvcache WHERE key = ? AND subKey = ?',
418
+ [storageKey, subKey]
419
+ );
450
420
  if (!row)
451
421
  return false;
452
422
  if (row.expiresAt !== null && Date.now() > row.expiresAt) {
@@ -458,13 +428,7 @@ const _SqliteAdapter = class _SqliteAdapter {
458
428
  async groupDel(key, subKey) {
459
429
  const client = this.getClient();
460
430
  const storageKey = this.prefixKey(key);
461
- await new Promise((res, rej) => {
462
- client.run(
463
- "DELETE FROM kvcache WHERE key = ? AND subKey = ?",
464
- [storageKey, subKey],
465
- (err) => err ? rej(err) : res()
466
- );
467
- });
431
+ return dbRun(client, "DELETE FROM kvcache WHERE key = ? AND subKey = ?", [storageKey, subKey]);
468
432
  }
469
433
  async close() {
470
434
  if (this.dbPath) {
@@ -854,4 +818,4 @@ const getAbtNodeRedisAndSQLiteUrl = () => {
854
818
  return params;
855
819
  };
856
820
 
857
- export { LockDBCache as DBCache, getAbtNodeRedisAndSQLiteUrl };
821
+ export { LockDBCache as DBCache, getAbtNodeRedisAndSQLiteUrl, withRetry };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abtnode/db-cache",
3
- "version": "1.16.47-beta-20250730-070104-87a128a5",
3
+ "version": "1.16.47-beta-20250731-014139-e860268f",
4
4
  "description": "Db cache use redis or sqlite as backend",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -45,5 +45,5 @@
45
45
  "typescript": "^5.6.3",
46
46
  "unbuild": "^2.0.0"
47
47
  },
48
- "gitHead": "a202f415488de553a2534d1a3d2a489dda27936c"
48
+ "gitHead": "85b5870be6b7a531cd7a86bd132112d68547fde1"
49
49
  }