@http-client-toolkit/store-sqlite 0.0.1 → 0.2.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/lib/index.cjs +467 -291
- package/lib/index.d.cts +573 -492
- package/lib/index.d.ts +573 -492
- package/lib/index.js +445 -284
- package/package.json +2 -2
package/lib/index.js
CHANGED
|
@@ -3,7 +3,10 @@ import { sql, eq, count, and, gt, lt, gte } from 'drizzle-orm';
|
|
|
3
3
|
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
4
4
|
import { sqliteTable, integer, blob, text } from 'drizzle-orm/sqlite-core';
|
|
5
5
|
import { randomUUID } from 'crypto';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
DEFAULT_RATE_LIMIT,
|
|
8
|
+
AdaptiveCapacityCalculator,
|
|
9
|
+
} from '@http-client-toolkit/core';
|
|
7
10
|
|
|
8
11
|
var __async = (__this, __arguments, generator) => {
|
|
9
12
|
return new Promise((resolve, reject) => {
|
|
@@ -21,48 +24,51 @@ var __async = (__this, __arguments, generator) => {
|
|
|
21
24
|
reject(e);
|
|
22
25
|
}
|
|
23
26
|
};
|
|
24
|
-
var step = (x) =>
|
|
27
|
+
var step = (x) =>
|
|
28
|
+
x.done
|
|
29
|
+
? resolve(x.value)
|
|
30
|
+
: Promise.resolve(x.value).then(fulfilled, rejected);
|
|
25
31
|
step((generator = generator.apply(__this, __arguments)).next());
|
|
26
32
|
});
|
|
27
33
|
};
|
|
28
|
-
var cacheTable = sqliteTable(
|
|
29
|
-
hash: text(
|
|
30
|
-
value: blob(
|
|
31
|
-
expiresAt: integer(
|
|
32
|
-
createdAt: integer(
|
|
34
|
+
var cacheTable = sqliteTable('cache', {
|
|
35
|
+
hash: text('hash').primaryKey(),
|
|
36
|
+
value: blob('value', { mode: 'json' }).notNull(),
|
|
37
|
+
expiresAt: integer('expires_at').notNull(),
|
|
38
|
+
createdAt: integer('created_at').notNull(),
|
|
33
39
|
});
|
|
34
|
-
var dedupeTable = sqliteTable(
|
|
35
|
-
hash: text(
|
|
36
|
-
jobId: text(
|
|
37
|
-
status: text(
|
|
40
|
+
var dedupeTable = sqliteTable('dedupe_jobs', {
|
|
41
|
+
hash: text('hash').primaryKey(),
|
|
42
|
+
jobId: text('job_id').notNull(),
|
|
43
|
+
status: text('status').notNull(),
|
|
38
44
|
// 'pending', 'completed', 'failed'
|
|
39
|
-
result: blob(
|
|
40
|
-
error: text(
|
|
41
|
-
createdAt: integer(
|
|
42
|
-
updatedAt: integer(
|
|
45
|
+
result: blob('result', { mode: 'json' }),
|
|
46
|
+
error: text('error'),
|
|
47
|
+
createdAt: integer('created_at').notNull(),
|
|
48
|
+
updatedAt: integer('updated_at').notNull(),
|
|
43
49
|
});
|
|
44
|
-
var rateLimitTable = sqliteTable(
|
|
45
|
-
resource: text(
|
|
46
|
-
timestamp: integer(
|
|
47
|
-
id: integer(
|
|
50
|
+
var rateLimitTable = sqliteTable('rate_limits', {
|
|
51
|
+
resource: text('resource').notNull(),
|
|
52
|
+
timestamp: integer('timestamp').notNull(),
|
|
53
|
+
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
48
54
|
});
|
|
49
55
|
|
|
50
56
|
// src/sqlite-cache-store.ts
|
|
51
57
|
var SQLiteCacheStore = class {
|
|
52
58
|
constructor({
|
|
53
59
|
/** File path or existing `better-sqlite3` connection. Defaults to `':memory:'`. */
|
|
54
|
-
database =
|
|
60
|
+
database = ':memory:',
|
|
55
61
|
/** Cleanup interval in milliseconds. Defaults to 1 minute. */
|
|
56
62
|
cleanupIntervalMs = 6e4,
|
|
57
63
|
/** Maximum allowed size (in bytes) for a single cache entry. Defaults to 5 MiB. */
|
|
58
|
-
maxEntrySizeBytes = 5 * 1024 * 1024
|
|
64
|
+
maxEntrySizeBytes = 5 * 1024 * 1024,
|
|
59
65
|
} = {}) {
|
|
60
66
|
/** Indicates whether this store is responsible for managing (and therefore closing) the SQLite connection */
|
|
61
67
|
this.isConnectionManaged = false;
|
|
62
68
|
this.isDestroyed = false;
|
|
63
69
|
let sqliteInstance;
|
|
64
70
|
let isConnectionManaged = false;
|
|
65
|
-
if (typeof database ===
|
|
71
|
+
if (typeof database === 'string') {
|
|
66
72
|
sqliteInstance = new Database(database);
|
|
67
73
|
isConnectionManaged = true;
|
|
68
74
|
} else {
|
|
@@ -79,9 +85,13 @@ var SQLiteCacheStore = class {
|
|
|
79
85
|
get(hash) {
|
|
80
86
|
return __async(this, null, function* () {
|
|
81
87
|
if (this.isDestroyed) {
|
|
82
|
-
throw new Error(
|
|
88
|
+
throw new Error('Cache store has been destroyed');
|
|
83
89
|
}
|
|
84
|
-
const result = yield this.db
|
|
90
|
+
const result = yield this.db
|
|
91
|
+
.select()
|
|
92
|
+
.from(cacheTable)
|
|
93
|
+
.where(eq(cacheTable.hash, hash))
|
|
94
|
+
.limit(1);
|
|
85
95
|
if (result.length === 0) {
|
|
86
96
|
return void 0;
|
|
87
97
|
}
|
|
@@ -95,7 +105,7 @@ var SQLiteCacheStore = class {
|
|
|
95
105
|
return void 0;
|
|
96
106
|
}
|
|
97
107
|
try {
|
|
98
|
-
if (item.value ===
|
|
108
|
+
if (item.value === '__UNDEFINED__') {
|
|
99
109
|
return void 0;
|
|
100
110
|
}
|
|
101
111
|
return JSON.parse(item.value);
|
|
@@ -108,44 +118,48 @@ var SQLiteCacheStore = class {
|
|
|
108
118
|
set(hash, value, ttlSeconds) {
|
|
109
119
|
return __async(this, null, function* () {
|
|
110
120
|
if (this.isDestroyed) {
|
|
111
|
-
throw new Error(
|
|
121
|
+
throw new Error('Cache store has been destroyed');
|
|
112
122
|
}
|
|
113
123
|
const now = Date.now();
|
|
114
|
-
const expiresAt =
|
|
124
|
+
const expiresAt =
|
|
125
|
+
ttlSeconds < 0 ? now : ttlSeconds === 0 ? 0 : now + ttlSeconds * 1e3;
|
|
115
126
|
let serializedValue;
|
|
116
127
|
try {
|
|
117
128
|
if (value === void 0) {
|
|
118
|
-
serializedValue =
|
|
129
|
+
serializedValue = '__UNDEFINED__';
|
|
119
130
|
} else {
|
|
120
131
|
serializedValue = JSON.stringify(value);
|
|
121
132
|
}
|
|
122
133
|
} catch (error) {
|
|
123
134
|
throw new Error(
|
|
124
|
-
`Failed to serialize value: ${error instanceof Error ? error.message : String(error)}
|
|
135
|
+
`Failed to serialize value: ${error instanceof Error ? error.message : String(error)}`,
|
|
125
136
|
);
|
|
126
137
|
}
|
|
127
|
-
if (Buffer.byteLength(serializedValue,
|
|
138
|
+
if (Buffer.byteLength(serializedValue, 'utf8') > this.maxEntrySizeBytes) {
|
|
128
139
|
return;
|
|
129
140
|
}
|
|
130
|
-
yield this.db
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
createdAt: now
|
|
135
|
-
}).onConflictDoUpdate({
|
|
136
|
-
target: cacheTable.hash,
|
|
137
|
-
set: {
|
|
141
|
+
yield this.db
|
|
142
|
+
.insert(cacheTable)
|
|
143
|
+
.values({
|
|
144
|
+
hash,
|
|
138
145
|
value: serializedValue,
|
|
139
146
|
expiresAt,
|
|
140
|
-
createdAt: now
|
|
141
|
-
}
|
|
142
|
-
|
|
147
|
+
createdAt: now,
|
|
148
|
+
})
|
|
149
|
+
.onConflictDoUpdate({
|
|
150
|
+
target: cacheTable.hash,
|
|
151
|
+
set: {
|
|
152
|
+
value: serializedValue,
|
|
153
|
+
expiresAt,
|
|
154
|
+
createdAt: now,
|
|
155
|
+
},
|
|
156
|
+
});
|
|
143
157
|
});
|
|
144
158
|
}
|
|
145
159
|
delete(hash) {
|
|
146
160
|
return __async(this, null, function* () {
|
|
147
161
|
if (this.isDestroyed) {
|
|
148
|
-
throw new Error(
|
|
162
|
+
throw new Error('Cache store has been destroyed');
|
|
149
163
|
}
|
|
150
164
|
yield this.db.delete(cacheTable).where(eq(cacheTable.hash, hash));
|
|
151
165
|
});
|
|
@@ -153,7 +167,7 @@ var SQLiteCacheStore = class {
|
|
|
153
167
|
clear() {
|
|
154
168
|
return __async(this, null, function* () {
|
|
155
169
|
if (this.isDestroyed) {
|
|
156
|
-
throw new Error(
|
|
170
|
+
throw new Error('Cache store has been destroyed');
|
|
157
171
|
}
|
|
158
172
|
yield this.db.delete(cacheTable);
|
|
159
173
|
});
|
|
@@ -165,19 +179,32 @@ var SQLiteCacheStore = class {
|
|
|
165
179
|
return __async(this, null, function* () {
|
|
166
180
|
var _a, _b, _c, _d;
|
|
167
181
|
const now = Date.now();
|
|
168
|
-
const totalResult = yield this.db
|
|
169
|
-
|
|
182
|
+
const totalResult = yield this.db
|
|
183
|
+
.select({ count: count() })
|
|
184
|
+
.from(cacheTable);
|
|
185
|
+
const expiredResult = yield this.db
|
|
186
|
+
.select({ count: count() })
|
|
187
|
+
.from(cacheTable)
|
|
188
|
+
.where(and(gt(cacheTable.expiresAt, 0), lt(cacheTable.expiresAt, now)));
|
|
170
189
|
const pageCount = Number(
|
|
171
|
-
this.sqlite.pragma(
|
|
190
|
+
this.sqlite.pragma('page_count', { simple: true }),
|
|
191
|
+
);
|
|
192
|
+
const pageSize = Number(
|
|
193
|
+
this.sqlite.pragma('page_size', { simple: true }),
|
|
172
194
|
);
|
|
173
|
-
const pageSize = Number(this.sqlite.pragma("page_size", { simple: true }));
|
|
174
195
|
const safePageCount = Number.isFinite(pageCount) ? pageCount : 0;
|
|
175
196
|
const safePageSize = Number.isFinite(pageSize) ? pageSize : 0;
|
|
176
|
-
const databaseSizeKB = Math.round(safePageCount * safePageSize / 1024);
|
|
197
|
+
const databaseSizeKB = Math.round((safePageCount * safePageSize) / 1024);
|
|
177
198
|
return {
|
|
178
199
|
databaseSizeKB,
|
|
179
|
-
expiredItems:
|
|
180
|
-
|
|
200
|
+
expiredItems:
|
|
201
|
+
(_b = (_a = expiredResult[0]) == null ? void 0 : _a.count) != null
|
|
202
|
+
? _b
|
|
203
|
+
: 0,
|
|
204
|
+
totalItems:
|
|
205
|
+
(_d = (_c = totalResult[0]) == null ? void 0 : _c.count) != null
|
|
206
|
+
? _d
|
|
207
|
+
: 0,
|
|
181
208
|
};
|
|
182
209
|
});
|
|
183
210
|
}
|
|
@@ -187,7 +214,9 @@ var SQLiteCacheStore = class {
|
|
|
187
214
|
cleanup() {
|
|
188
215
|
return __async(this, null, function* () {
|
|
189
216
|
const now = Date.now();
|
|
190
|
-
yield this.db
|
|
217
|
+
yield this.db
|
|
218
|
+
.delete(cacheTable)
|
|
219
|
+
.where(and(gt(cacheTable.expiresAt, 0), lt(cacheTable.expiresAt, now)));
|
|
191
220
|
});
|
|
192
221
|
}
|
|
193
222
|
/**
|
|
@@ -200,7 +229,7 @@ var SQLiteCacheStore = class {
|
|
|
200
229
|
this.cleanupInterval = void 0;
|
|
201
230
|
}
|
|
202
231
|
this.isDestroyed = true;
|
|
203
|
-
if (this.isConnectionManaged && typeof this.sqlite.close ===
|
|
232
|
+
if (this.isConnectionManaged && typeof this.sqlite.close === 'function') {
|
|
204
233
|
this.sqlite.close();
|
|
205
234
|
}
|
|
206
235
|
});
|
|
@@ -228,10 +257,14 @@ var SQLiteCacheStore = class {
|
|
|
228
257
|
if (this.cleanupIntervalMs <= 0) {
|
|
229
258
|
return;
|
|
230
259
|
}
|
|
231
|
-
this.cleanupInterval = setInterval(
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
260
|
+
this.cleanupInterval = setInterval(
|
|
261
|
+
() =>
|
|
262
|
+
__async(this, null, function* () {
|
|
263
|
+
yield this.cleanup();
|
|
264
|
+
}),
|
|
265
|
+
this.cleanupIntervalMs,
|
|
266
|
+
);
|
|
267
|
+
if (typeof this.cleanupInterval.unref === 'function') {
|
|
235
268
|
this.cleanupInterval.unref();
|
|
236
269
|
}
|
|
237
270
|
}
|
|
@@ -245,7 +278,7 @@ var SQLiteCacheStore = class {
|
|
|
245
278
|
var SQLiteDedupeStore = class {
|
|
246
279
|
constructor({
|
|
247
280
|
/** File path or existing `better-sqlite3` Database instance. Defaults to `':memory:'`. */
|
|
248
|
-
database =
|
|
281
|
+
database = ':memory:',
|
|
249
282
|
/** Job timeout in milliseconds. Preferred over timeoutMs. */
|
|
250
283
|
jobTimeoutMs,
|
|
251
284
|
/** Legacy alias for jobTimeoutMs. */
|
|
@@ -253,7 +286,7 @@ var SQLiteDedupeStore = class {
|
|
|
253
286
|
/** Cleanup interval in milliseconds. Defaults to 1 minute. */
|
|
254
287
|
cleanupIntervalMs = 6e4,
|
|
255
288
|
/** Poll interval for checking pending jobs in milliseconds. Defaults to 100ms. */
|
|
256
|
-
pollIntervalMs = 100
|
|
289
|
+
pollIntervalMs = 100,
|
|
257
290
|
} = {}) {
|
|
258
291
|
/** Indicates whether this store manages (and should close) the SQLite connection */
|
|
259
292
|
this.isConnectionManaged = false;
|
|
@@ -263,7 +296,7 @@ var SQLiteDedupeStore = class {
|
|
|
263
296
|
var _a;
|
|
264
297
|
let sqliteInstance;
|
|
265
298
|
let isConnectionManaged = false;
|
|
266
|
-
if (typeof database ===
|
|
299
|
+
if (typeof database === 'string') {
|
|
267
300
|
sqliteInstance = new Database(database);
|
|
268
301
|
isConnectionManaged = true;
|
|
269
302
|
} else {
|
|
@@ -272,7 +305,8 @@ var SQLiteDedupeStore = class {
|
|
|
272
305
|
this.sqlite = sqliteInstance;
|
|
273
306
|
this.isConnectionManaged = isConnectionManaged;
|
|
274
307
|
this.db = drizzle(sqliteInstance);
|
|
275
|
-
this.jobTimeoutMs =
|
|
308
|
+
this.jobTimeoutMs =
|
|
309
|
+
(_a = timeoutMs != null ? timeoutMs : jobTimeoutMs) != null ? _a : 3e5;
|
|
276
310
|
this.cleanupIntervalMs = cleanupIntervalMs;
|
|
277
311
|
this.pollIntervalMs = pollIntervalMs;
|
|
278
312
|
this.initializeDatabase();
|
|
@@ -281,10 +315,9 @@ var SQLiteDedupeStore = class {
|
|
|
281
315
|
startCleanupInterval() {
|
|
282
316
|
if (this.cleanupIntervalMs > 0) {
|
|
283
317
|
this.cleanupInterval = setInterval(() => {
|
|
284
|
-
this.cleanupExpiredJobs().catch(() => {
|
|
285
|
-
});
|
|
318
|
+
this.cleanupExpiredJobs().catch(() => {});
|
|
286
319
|
}, this.cleanupIntervalMs);
|
|
287
|
-
if (typeof this.cleanupInterval.unref ===
|
|
320
|
+
if (typeof this.cleanupInterval.unref === 'function') {
|
|
288
321
|
this.cleanupInterval.unref();
|
|
289
322
|
}
|
|
290
323
|
}
|
|
@@ -297,18 +330,20 @@ var SQLiteDedupeStore = class {
|
|
|
297
330
|
}
|
|
298
331
|
const now = Date.now();
|
|
299
332
|
const expiredThreshold = now - this.jobTimeoutMs;
|
|
300
|
-
yield this.db
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
333
|
+
yield this.db
|
|
334
|
+
.delete(dedupeTable)
|
|
335
|
+
.where(
|
|
336
|
+
and(
|
|
337
|
+
eq(dedupeTable.status, 'pending'),
|
|
338
|
+
lt(dedupeTable.createdAt, expiredThreshold),
|
|
339
|
+
),
|
|
340
|
+
);
|
|
306
341
|
});
|
|
307
342
|
}
|
|
308
343
|
waitFor(hash) {
|
|
309
344
|
return __async(this, null, function* () {
|
|
310
345
|
if (this.isDestroyed) {
|
|
311
|
-
throw new Error(
|
|
346
|
+
throw new Error('Dedupe store has been destroyed');
|
|
312
347
|
}
|
|
313
348
|
const existingPromise = this.jobPromises.get(hash);
|
|
314
349
|
if (existingPromise) {
|
|
@@ -316,7 +351,11 @@ var SQLiteDedupeStore = class {
|
|
|
316
351
|
}
|
|
317
352
|
let result;
|
|
318
353
|
try {
|
|
319
|
-
result = yield this.db
|
|
354
|
+
result = yield this.db
|
|
355
|
+
.select()
|
|
356
|
+
.from(dedupeTable)
|
|
357
|
+
.where(eq(dedupeTable.hash, hash))
|
|
358
|
+
.limit(1);
|
|
320
359
|
} catch (e) {
|
|
321
360
|
return void 0;
|
|
322
361
|
}
|
|
@@ -327,10 +366,10 @@ var SQLiteDedupeStore = class {
|
|
|
327
366
|
if (!job) {
|
|
328
367
|
return void 0;
|
|
329
368
|
}
|
|
330
|
-
if (job.status ===
|
|
369
|
+
if (job.status === 'completed') {
|
|
331
370
|
return this.deserializeResult(job.result);
|
|
332
371
|
}
|
|
333
|
-
if (job.status ===
|
|
372
|
+
if (job.status === 'failed') {
|
|
334
373
|
return void 0;
|
|
335
374
|
}
|
|
336
375
|
const promise = new Promise((resolve) => {
|
|
@@ -350,43 +389,53 @@ var SQLiteDedupeStore = class {
|
|
|
350
389
|
resolve(value);
|
|
351
390
|
};
|
|
352
391
|
this.jobSettlers.set(hash, settle);
|
|
353
|
-
const poll = () =>
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
try {
|
|
359
|
-
const latest = yield this.db.select().from(dedupeTable).where(eq(dedupeTable.hash, hash)).limit(1);
|
|
360
|
-
const latestJob = latest[0];
|
|
361
|
-
if (!latestJob) {
|
|
362
|
-
settle(void 0);
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
const isExpired = this.jobTimeoutMs > 0 && Date.now() - latestJob.createdAt >= this.jobTimeoutMs;
|
|
366
|
-
if (isExpired) {
|
|
367
|
-
yield this.db.update(dedupeTable).set({
|
|
368
|
-
status: "failed",
|
|
369
|
-
error: "Job timed out",
|
|
370
|
-
updatedAt: Date.now()
|
|
371
|
-
}).where(eq(dedupeTable.hash, hash));
|
|
392
|
+
const poll = () =>
|
|
393
|
+
__async(this, null, function* () {
|
|
394
|
+
if (this.isDestroyed) {
|
|
372
395
|
settle(void 0);
|
|
373
396
|
return;
|
|
374
397
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
398
|
+
try {
|
|
399
|
+
const latest = yield this.db
|
|
400
|
+
.select()
|
|
401
|
+
.from(dedupeTable)
|
|
402
|
+
.where(eq(dedupeTable.hash, hash))
|
|
403
|
+
.limit(1);
|
|
404
|
+
const latestJob = latest[0];
|
|
405
|
+
if (!latestJob) {
|
|
406
|
+
settle(void 0);
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
const isExpired =
|
|
410
|
+
this.jobTimeoutMs > 0 &&
|
|
411
|
+
Date.now() - latestJob.createdAt >= this.jobTimeoutMs;
|
|
412
|
+
if (isExpired) {
|
|
413
|
+
yield this.db
|
|
414
|
+
.update(dedupeTable)
|
|
415
|
+
.set({
|
|
416
|
+
status: 'failed',
|
|
417
|
+
error: 'Job timed out',
|
|
418
|
+
updatedAt: Date.now(),
|
|
419
|
+
})
|
|
420
|
+
.where(eq(dedupeTable.hash, hash));
|
|
421
|
+
settle(void 0);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
if (latestJob.status === 'completed') {
|
|
425
|
+
settle(this.deserializeResult(latestJob.result));
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
if (latestJob.status === 'failed') {
|
|
429
|
+
settle(void 0);
|
|
430
|
+
}
|
|
431
|
+
} catch (e) {
|
|
380
432
|
settle(void 0);
|
|
381
433
|
}
|
|
382
|
-
}
|
|
383
|
-
settle(void 0);
|
|
384
|
-
}
|
|
385
|
-
});
|
|
434
|
+
});
|
|
386
435
|
const pollHandle = setInterval(() => {
|
|
387
436
|
void poll();
|
|
388
437
|
}, this.pollIntervalMs);
|
|
389
|
-
if (typeof pollHandle.unref ===
|
|
438
|
+
if (typeof pollHandle.unref === 'function') {
|
|
390
439
|
pollHandle.unref();
|
|
391
440
|
}
|
|
392
441
|
void poll();
|
|
@@ -396,20 +445,24 @@ var SQLiteDedupeStore = class {
|
|
|
396
445
|
settle(void 0);
|
|
397
446
|
return;
|
|
398
447
|
}
|
|
399
|
-
void (() =>
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
448
|
+
void (() =>
|
|
449
|
+
__async(this, null, function* () {
|
|
450
|
+
try {
|
|
451
|
+
yield this.db
|
|
452
|
+
.update(dedupeTable)
|
|
453
|
+
.set({
|
|
454
|
+
status: 'failed',
|
|
455
|
+
error: 'Job timed out',
|
|
456
|
+
updatedAt: Date.now(),
|
|
457
|
+
})
|
|
458
|
+
.where(eq(dedupeTable.hash, hash));
|
|
459
|
+
} catch (e) {
|
|
460
|
+
} finally {
|
|
461
|
+
settle(void 0);
|
|
462
|
+
}
|
|
463
|
+
}))();
|
|
411
464
|
}, this.jobTimeoutMs);
|
|
412
|
-
if (typeof timeoutHandle.unref ===
|
|
465
|
+
if (typeof timeoutHandle.unref === 'function') {
|
|
413
466
|
timeoutHandle.unref();
|
|
414
467
|
}
|
|
415
468
|
}
|
|
@@ -427,23 +480,26 @@ var SQLiteDedupeStore = class {
|
|
|
427
480
|
registerOrJoin(hash) {
|
|
428
481
|
return __async(this, null, function* () {
|
|
429
482
|
if (this.isDestroyed) {
|
|
430
|
-
throw new Error(
|
|
483
|
+
throw new Error('Dedupe store has been destroyed');
|
|
431
484
|
}
|
|
432
485
|
const now = Date.now();
|
|
433
486
|
const candidateJobId = randomUUID();
|
|
434
487
|
const registerTransaction = this.sqlite.transaction(
|
|
435
488
|
(requestHash, createdAt, jobId) => {
|
|
436
|
-
const existing = this.sqlite
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
489
|
+
const existing = this.sqlite
|
|
490
|
+
.prepare(
|
|
491
|
+
'SELECT job_id as jobId, status FROM dedupe_jobs WHERE hash = ? LIMIT 1',
|
|
492
|
+
)
|
|
493
|
+
.get(requestHash);
|
|
494
|
+
if (existing && existing.status === 'pending') {
|
|
440
495
|
return {
|
|
441
496
|
jobId: existing.jobId,
|
|
442
|
-
isOwner: false
|
|
497
|
+
isOwner: false,
|
|
443
498
|
};
|
|
444
499
|
}
|
|
445
|
-
this.sqlite
|
|
446
|
-
|
|
500
|
+
this.sqlite
|
|
501
|
+
.prepare(
|
|
502
|
+
`
|
|
447
503
|
INSERT INTO dedupe_jobs (hash, job_id, status, result, error, created_at, updated_at)
|
|
448
504
|
VALUES (?, ?, 'pending', NULL, NULL, ?, ?)
|
|
449
505
|
ON CONFLICT(hash) DO UPDATE SET
|
|
@@ -453,13 +509,14 @@ var SQLiteDedupeStore = class {
|
|
|
453
509
|
error = NULL,
|
|
454
510
|
created_at = excluded.created_at,
|
|
455
511
|
updated_at = excluded.updated_at
|
|
456
|
-
|
|
457
|
-
|
|
512
|
+
`,
|
|
513
|
+
)
|
|
514
|
+
.run(requestHash, jobId, createdAt, createdAt);
|
|
458
515
|
return {
|
|
459
516
|
jobId,
|
|
460
|
-
isOwner: true
|
|
517
|
+
isOwner: true,
|
|
461
518
|
};
|
|
462
|
-
}
|
|
519
|
+
},
|
|
463
520
|
);
|
|
464
521
|
return registerTransaction(hash, now, candidateJobId);
|
|
465
522
|
});
|
|
@@ -468,32 +525,42 @@ var SQLiteDedupeStore = class {
|
|
|
468
525
|
return __async(this, null, function* () {
|
|
469
526
|
var _a;
|
|
470
527
|
if (this.isDestroyed) {
|
|
471
|
-
throw new Error(
|
|
528
|
+
throw new Error('Dedupe store has been destroyed');
|
|
472
529
|
}
|
|
473
530
|
let serializedResult;
|
|
474
531
|
if (value === void 0) {
|
|
475
|
-
serializedResult =
|
|
532
|
+
serializedResult = '__UNDEFINED__';
|
|
476
533
|
} else if (value === null) {
|
|
477
|
-
serializedResult =
|
|
534
|
+
serializedResult = '__NULL__';
|
|
478
535
|
} else {
|
|
479
536
|
try {
|
|
480
537
|
serializedResult = JSON.stringify(value);
|
|
481
538
|
} catch (error) {
|
|
482
539
|
throw new Error(
|
|
483
|
-
`Failed to serialize result: ${error instanceof Error ? error.message : String(error)}
|
|
540
|
+
`Failed to serialize result: ${error instanceof Error ? error.message : String(error)}`,
|
|
484
541
|
);
|
|
485
542
|
}
|
|
486
543
|
}
|
|
487
544
|
const now = Date.now();
|
|
488
|
-
const existingJob = yield this.db
|
|
489
|
-
|
|
545
|
+
const existingJob = yield this.db
|
|
546
|
+
.select()
|
|
547
|
+
.from(dedupeTable)
|
|
548
|
+
.where(eq(dedupeTable.hash, hash))
|
|
549
|
+
.limit(1);
|
|
550
|
+
if (
|
|
551
|
+
existingJob.length > 0 &&
|
|
552
|
+
((_a = existingJob[0]) == null ? void 0 : _a.status) === 'completed'
|
|
553
|
+
) {
|
|
490
554
|
return;
|
|
491
555
|
}
|
|
492
|
-
yield this.db
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
556
|
+
yield this.db
|
|
557
|
+
.update(dedupeTable)
|
|
558
|
+
.set({
|
|
559
|
+
status: 'completed',
|
|
560
|
+
result: serializedResult,
|
|
561
|
+
updatedAt: now,
|
|
562
|
+
})
|
|
563
|
+
.where(eq(dedupeTable.hash, hash));
|
|
497
564
|
const settle = this.jobSettlers.get(hash);
|
|
498
565
|
if (settle) {
|
|
499
566
|
settle(value);
|
|
@@ -503,14 +570,17 @@ var SQLiteDedupeStore = class {
|
|
|
503
570
|
fail(hash, error) {
|
|
504
571
|
return __async(this, null, function* () {
|
|
505
572
|
if (this.isDestroyed) {
|
|
506
|
-
throw new Error(
|
|
573
|
+
throw new Error('Dedupe store has been destroyed');
|
|
507
574
|
}
|
|
508
575
|
const now = Date.now();
|
|
509
|
-
yield this.db
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
576
|
+
yield this.db
|
|
577
|
+
.update(dedupeTable)
|
|
578
|
+
.set({
|
|
579
|
+
status: 'failed',
|
|
580
|
+
error: error.message,
|
|
581
|
+
updatedAt: now,
|
|
582
|
+
})
|
|
583
|
+
.where(eq(dedupeTable.hash, hash));
|
|
514
584
|
const settle = this.jobSettlers.get(hash);
|
|
515
585
|
if (settle) {
|
|
516
586
|
settle(void 0);
|
|
@@ -520,9 +590,13 @@ var SQLiteDedupeStore = class {
|
|
|
520
590
|
isInProgress(hash) {
|
|
521
591
|
return __async(this, null, function* () {
|
|
522
592
|
if (this.isDestroyed) {
|
|
523
|
-
throw new Error(
|
|
593
|
+
throw new Error('Dedupe store has been destroyed');
|
|
524
594
|
}
|
|
525
|
-
const result = yield this.db
|
|
595
|
+
const result = yield this.db
|
|
596
|
+
.select()
|
|
597
|
+
.from(dedupeTable)
|
|
598
|
+
.where(eq(dedupeTable.hash, hash))
|
|
599
|
+
.limit(1);
|
|
526
600
|
if (result.length === 0) {
|
|
527
601
|
return false;
|
|
528
602
|
}
|
|
@@ -530,17 +604,23 @@ var SQLiteDedupeStore = class {
|
|
|
530
604
|
if (!job) {
|
|
531
605
|
return false;
|
|
532
606
|
}
|
|
533
|
-
const jobExpired =
|
|
607
|
+
const jobExpired =
|
|
608
|
+
this.jobTimeoutMs > 0 &&
|
|
609
|
+
Date.now() - job.createdAt >= this.jobTimeoutMs;
|
|
534
610
|
if (jobExpired) {
|
|
535
611
|
yield this.db.delete(dedupeTable).where(eq(dedupeTable.hash, hash));
|
|
536
612
|
return false;
|
|
537
613
|
}
|
|
538
|
-
return job.status ===
|
|
614
|
+
return job.status === 'pending';
|
|
539
615
|
});
|
|
540
616
|
}
|
|
541
617
|
getResult(hash) {
|
|
542
618
|
return __async(this, null, function* () {
|
|
543
|
-
const result = yield this.db
|
|
619
|
+
const result = yield this.db
|
|
620
|
+
.select()
|
|
621
|
+
.from(dedupeTable)
|
|
622
|
+
.where(eq(dedupeTable.hash, hash))
|
|
623
|
+
.limit(1);
|
|
544
624
|
if (result.length === 0) {
|
|
545
625
|
return void 0;
|
|
546
626
|
}
|
|
@@ -554,11 +634,11 @@ var SQLiteDedupeStore = class {
|
|
|
554
634
|
yield this.db.delete(dedupeTable).where(eq(dedupeTable.hash, hash));
|
|
555
635
|
return void 0;
|
|
556
636
|
}
|
|
557
|
-
if (job.status ===
|
|
637
|
+
if (job.status === 'completed') {
|
|
558
638
|
try {
|
|
559
|
-
if (job.result ===
|
|
639
|
+
if (job.result === '__UNDEFINED__') {
|
|
560
640
|
return void 0;
|
|
561
|
-
} else if (job.result ===
|
|
641
|
+
} else if (job.result === '__NULL__') {
|
|
562
642
|
return null;
|
|
563
643
|
} else if (job.result) {
|
|
564
644
|
return JSON.parse(job.result);
|
|
@@ -579,17 +659,32 @@ var SQLiteDedupeStore = class {
|
|
|
579
659
|
var _a, _b, _c, _d, _e;
|
|
580
660
|
const now = Date.now();
|
|
581
661
|
const expiredTime = now - this.jobTimeoutMs;
|
|
582
|
-
const totalResult = yield this.db
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
const
|
|
586
|
-
|
|
662
|
+
const totalResult = yield this.db
|
|
663
|
+
.select({ count: count() })
|
|
664
|
+
.from(dedupeTable);
|
|
665
|
+
const pendingResult = yield this.db
|
|
666
|
+
.select({ count: count() })
|
|
667
|
+
.from(dedupeTable)
|
|
668
|
+
.where(eq(dedupeTable.status, 'pending'));
|
|
669
|
+
const completedResult = yield this.db
|
|
670
|
+
.select({ count: count() })
|
|
671
|
+
.from(dedupeTable)
|
|
672
|
+
.where(eq(dedupeTable.status, 'completed'));
|
|
673
|
+
const failedResult = yield this.db
|
|
674
|
+
.select({ count: count() })
|
|
675
|
+
.from(dedupeTable)
|
|
676
|
+
.where(eq(dedupeTable.status, 'failed'));
|
|
677
|
+
const expiredResult = yield this.db
|
|
678
|
+
.select({ count: count() })
|
|
679
|
+
.from(dedupeTable)
|
|
680
|
+
.where(lt(dedupeTable.createdAt, expiredTime));
|
|
587
681
|
return {
|
|
588
682
|
totalJobs: ((_a = totalResult[0]) == null ? void 0 : _a.count) || 0,
|
|
589
683
|
pendingJobs: ((_b = pendingResult[0]) == null ? void 0 : _b.count) || 0,
|
|
590
|
-
completedJobs:
|
|
684
|
+
completedJobs:
|
|
685
|
+
((_c = completedResult[0]) == null ? void 0 : _c.count) || 0,
|
|
591
686
|
failedJobs: ((_d = failedResult[0]) == null ? void 0 : _d.count) || 0,
|
|
592
|
-
expiredJobs: ((_e = expiredResult[0]) == null ? void 0 : _e.count) || 0
|
|
687
|
+
expiredJobs: ((_e = expiredResult[0]) == null ? void 0 : _e.count) || 0,
|
|
593
688
|
};
|
|
594
689
|
});
|
|
595
690
|
}
|
|
@@ -600,7 +695,9 @@ var SQLiteDedupeStore = class {
|
|
|
600
695
|
return __async(this, null, function* () {
|
|
601
696
|
const now = Date.now();
|
|
602
697
|
const expiredTime = now - this.jobTimeoutMs;
|
|
603
|
-
yield this.db
|
|
698
|
+
yield this.db
|
|
699
|
+
.delete(dedupeTable)
|
|
700
|
+
.where(lt(dedupeTable.createdAt, expiredTime));
|
|
604
701
|
});
|
|
605
702
|
}
|
|
606
703
|
/**
|
|
@@ -631,7 +728,7 @@ var SQLiteDedupeStore = class {
|
|
|
631
728
|
}
|
|
632
729
|
this.jobPromises.clear();
|
|
633
730
|
this.jobSettlers.clear();
|
|
634
|
-
if (this.isConnectionManaged && typeof this.sqlite.close ===
|
|
731
|
+
if (this.isConnectionManaged && typeof this.sqlite.close === 'function') {
|
|
635
732
|
this.sqlite.close();
|
|
636
733
|
}
|
|
637
734
|
});
|
|
@@ -644,10 +741,10 @@ var SQLiteDedupeStore = class {
|
|
|
644
741
|
}
|
|
645
742
|
deserializeResult(serializedResult) {
|
|
646
743
|
try {
|
|
647
|
-
if (serializedResult ===
|
|
744
|
+
if (serializedResult === '__UNDEFINED__') {
|
|
648
745
|
return void 0;
|
|
649
746
|
}
|
|
650
|
-
if (serializedResult ===
|
|
747
|
+
if (serializedResult === '__NULL__') {
|
|
651
748
|
return null;
|
|
652
749
|
}
|
|
653
750
|
if (serializedResult) {
|
|
@@ -678,11 +775,11 @@ var SQLiteDedupeStore = class {
|
|
|
678
775
|
var SQLiteRateLimitStore = class {
|
|
679
776
|
constructor({
|
|
680
777
|
/** File path or existing `better-sqlite3` Database instance. Defaults to `':memory:'`. */
|
|
681
|
-
database =
|
|
778
|
+
database = ':memory:',
|
|
682
779
|
/** Global/default rate-limit config applied when a resource-specific override is not provided. */
|
|
683
780
|
defaultConfig = DEFAULT_RATE_LIMIT,
|
|
684
781
|
/** Optional per-resource overrides. */
|
|
685
|
-
resourceConfigs = /* @__PURE__ */ new Map()
|
|
782
|
+
resourceConfigs = /* @__PURE__ */ new Map(),
|
|
686
783
|
} = {}) {
|
|
687
784
|
/** Indicates whether this store manages (and should close) the SQLite connection */
|
|
688
785
|
this.isConnectionManaged = false;
|
|
@@ -690,7 +787,7 @@ var SQLiteRateLimitStore = class {
|
|
|
690
787
|
this.isDestroyed = false;
|
|
691
788
|
let sqliteInstance;
|
|
692
789
|
let isConnectionManaged = false;
|
|
693
|
-
if (typeof database ===
|
|
790
|
+
if (typeof database === 'string') {
|
|
694
791
|
sqliteInstance = new Database(database);
|
|
695
792
|
isConnectionManaged = true;
|
|
696
793
|
} else {
|
|
@@ -707,18 +804,21 @@ var SQLiteRateLimitStore = class {
|
|
|
707
804
|
return __async(this, null, function* () {
|
|
708
805
|
var _a;
|
|
709
806
|
if (this.isDestroyed) {
|
|
710
|
-
throw new Error(
|
|
807
|
+
throw new Error('Rate limit store has been destroyed');
|
|
711
808
|
}
|
|
712
809
|
const config = this.resourceConfigs.get(resource) || this.defaultConfig;
|
|
713
810
|
const now = Date.now();
|
|
714
811
|
const windowStart = now - config.windowMs;
|
|
715
812
|
yield this.cleanupExpiredRequests(resource, windowStart);
|
|
716
|
-
const result = yield this.db
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
813
|
+
const result = yield this.db
|
|
814
|
+
.select({ count: count() })
|
|
815
|
+
.from(rateLimitTable)
|
|
816
|
+
.where(
|
|
817
|
+
and(
|
|
818
|
+
eq(rateLimitTable.resource, resource),
|
|
819
|
+
gte(rateLimitTable.timestamp, windowStart),
|
|
820
|
+
),
|
|
821
|
+
);
|
|
722
822
|
const currentCount = ((_a = result[0]) == null ? void 0 : _a.count) || 0;
|
|
723
823
|
return currentCount < config.limit;
|
|
724
824
|
});
|
|
@@ -726,12 +826,12 @@ var SQLiteRateLimitStore = class {
|
|
|
726
826
|
record(resource) {
|
|
727
827
|
return __async(this, null, function* () {
|
|
728
828
|
if (this.isDestroyed) {
|
|
729
|
-
throw new Error(
|
|
829
|
+
throw new Error('Rate limit store has been destroyed');
|
|
730
830
|
}
|
|
731
831
|
const now = Date.now();
|
|
732
832
|
yield this.db.insert(rateLimitTable).values({
|
|
733
833
|
resource,
|
|
734
|
-
timestamp: now
|
|
834
|
+
timestamp: now,
|
|
735
835
|
});
|
|
736
836
|
});
|
|
737
837
|
}
|
|
@@ -739,41 +839,47 @@ var SQLiteRateLimitStore = class {
|
|
|
739
839
|
return __async(this, null, function* () {
|
|
740
840
|
var _a;
|
|
741
841
|
if (this.isDestroyed) {
|
|
742
|
-
throw new Error(
|
|
842
|
+
throw new Error('Rate limit store has been destroyed');
|
|
743
843
|
}
|
|
744
844
|
const config = this.resourceConfigs.get(resource) || this.defaultConfig;
|
|
745
845
|
const now = Date.now();
|
|
746
846
|
const windowStart = now - config.windowMs;
|
|
747
847
|
yield this.cleanupExpiredRequests(resource, windowStart);
|
|
748
|
-
const result = yield this.db
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
848
|
+
const result = yield this.db
|
|
849
|
+
.select({ count: count() })
|
|
850
|
+
.from(rateLimitTable)
|
|
851
|
+
.where(
|
|
852
|
+
and(
|
|
853
|
+
eq(rateLimitTable.resource, resource),
|
|
854
|
+
gte(rateLimitTable.timestamp, windowStart),
|
|
855
|
+
),
|
|
856
|
+
);
|
|
857
|
+
const currentRequests =
|
|
858
|
+
((_a = result[0]) == null ? void 0 : _a.count) || 0;
|
|
755
859
|
const remaining = Math.max(0, config.limit - currentRequests);
|
|
756
860
|
const resetTime = new Date(now + config.windowMs);
|
|
757
861
|
return {
|
|
758
862
|
remaining,
|
|
759
863
|
resetTime,
|
|
760
|
-
limit: config.limit
|
|
864
|
+
limit: config.limit,
|
|
761
865
|
};
|
|
762
866
|
});
|
|
763
867
|
}
|
|
764
868
|
reset(resource) {
|
|
765
869
|
return __async(this, null, function* () {
|
|
766
870
|
if (this.isDestroyed) {
|
|
767
|
-
throw new Error(
|
|
871
|
+
throw new Error('Rate limit store has been destroyed');
|
|
768
872
|
}
|
|
769
|
-
yield this.db
|
|
873
|
+
yield this.db
|
|
874
|
+
.delete(rateLimitTable)
|
|
875
|
+
.where(eq(rateLimitTable.resource, resource));
|
|
770
876
|
});
|
|
771
877
|
}
|
|
772
878
|
getWaitTime(resource) {
|
|
773
879
|
return __async(this, null, function* () {
|
|
774
880
|
var _a, _b;
|
|
775
881
|
if (this.isDestroyed) {
|
|
776
|
-
throw new Error(
|
|
882
|
+
throw new Error('Rate limit store has been destroyed');
|
|
777
883
|
}
|
|
778
884
|
const config = this.resourceConfigs.get(resource) || this.defaultConfig;
|
|
779
885
|
if (config.limit === 0) {
|
|
@@ -782,26 +888,36 @@ var SQLiteRateLimitStore = class {
|
|
|
782
888
|
const now = Date.now();
|
|
783
889
|
const windowStart = now - config.windowMs;
|
|
784
890
|
yield this.cleanupExpiredRequests(resource, windowStart);
|
|
785
|
-
const countResult = yield this.db
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
891
|
+
const countResult = yield this.db
|
|
892
|
+
.select({ count: count() })
|
|
893
|
+
.from(rateLimitTable)
|
|
894
|
+
.where(
|
|
895
|
+
and(
|
|
896
|
+
eq(rateLimitTable.resource, resource),
|
|
897
|
+
gte(rateLimitTable.timestamp, windowStart),
|
|
898
|
+
),
|
|
899
|
+
);
|
|
900
|
+
const currentRequests =
|
|
901
|
+
((_a = countResult[0]) == null ? void 0 : _a.count) || 0;
|
|
792
902
|
if (currentRequests < config.limit) {
|
|
793
903
|
return 0;
|
|
794
904
|
}
|
|
795
|
-
const oldestResult = yield this.db
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
905
|
+
const oldestResult = yield this.db
|
|
906
|
+
.select({ timestamp: rateLimitTable.timestamp })
|
|
907
|
+
.from(rateLimitTable)
|
|
908
|
+
.where(
|
|
909
|
+
and(
|
|
910
|
+
eq(rateLimitTable.resource, resource),
|
|
911
|
+
gte(rateLimitTable.timestamp, windowStart),
|
|
912
|
+
),
|
|
799
913
|
)
|
|
800
|
-
|
|
914
|
+
.orderBy(rateLimitTable.timestamp)
|
|
915
|
+
.limit(1);
|
|
801
916
|
if (oldestResult.length === 0) {
|
|
802
917
|
return 0;
|
|
803
918
|
}
|
|
804
|
-
const oldestTimestamp =
|
|
919
|
+
const oldestTimestamp =
|
|
920
|
+
(_b = oldestResult[0]) == null ? void 0 : _b.timestamp;
|
|
805
921
|
if (oldestTimestamp === void 0) {
|
|
806
922
|
return 0;
|
|
807
923
|
}
|
|
@@ -828,10 +944,15 @@ var SQLiteRateLimitStore = class {
|
|
|
828
944
|
return __async(this, null, function* () {
|
|
829
945
|
var _a;
|
|
830
946
|
if (this.isDestroyed) {
|
|
831
|
-
throw new Error(
|
|
832
|
-
}
|
|
833
|
-
const totalResult = yield this.db
|
|
834
|
-
|
|
947
|
+
throw new Error('Rate limit store has been destroyed');
|
|
948
|
+
}
|
|
949
|
+
const totalResult = yield this.db
|
|
950
|
+
.select({ count: count() })
|
|
951
|
+
.from(rateLimitTable);
|
|
952
|
+
const resourcesResult = yield this.db
|
|
953
|
+
.select({ resource: rateLimitTable.resource })
|
|
954
|
+
.from(rateLimitTable)
|
|
955
|
+
.groupBy(rateLimitTable.resource);
|
|
835
956
|
const uniqueResources = resourcesResult.length;
|
|
836
957
|
const rateLimitedResources = [];
|
|
837
958
|
for (const { resource } of resourcesResult) {
|
|
@@ -843,7 +964,7 @@ var SQLiteRateLimitStore = class {
|
|
|
843
964
|
return {
|
|
844
965
|
totalRequests: ((_a = totalResult[0]) == null ? void 0 : _a.count) || 0,
|
|
845
966
|
uniqueResources,
|
|
846
|
-
rateLimitedResources
|
|
967
|
+
rateLimitedResources,
|
|
847
968
|
};
|
|
848
969
|
});
|
|
849
970
|
}
|
|
@@ -853,7 +974,7 @@ var SQLiteRateLimitStore = class {
|
|
|
853
974
|
clear() {
|
|
854
975
|
return __async(this, null, function* () {
|
|
855
976
|
if (this.isDestroyed) {
|
|
856
|
-
throw new Error(
|
|
977
|
+
throw new Error('Rate limit store has been destroyed');
|
|
857
978
|
}
|
|
858
979
|
yield this.db.delete(rateLimitTable);
|
|
859
980
|
});
|
|
@@ -864,7 +985,10 @@ var SQLiteRateLimitStore = class {
|
|
|
864
985
|
cleanup() {
|
|
865
986
|
return __async(this, null, function* () {
|
|
866
987
|
const now = Date.now();
|
|
867
|
-
const resources = yield this.db
|
|
988
|
+
const resources = yield this.db
|
|
989
|
+
.select({ resource: rateLimitTable.resource })
|
|
990
|
+
.from(rateLimitTable)
|
|
991
|
+
.groupBy(rateLimitTable.resource);
|
|
868
992
|
for (const { resource } of resources) {
|
|
869
993
|
const config = this.resourceConfigs.get(resource) || this.defaultConfig;
|
|
870
994
|
const windowStart = now - config.windowMs;
|
|
@@ -878,7 +1002,7 @@ var SQLiteRateLimitStore = class {
|
|
|
878
1002
|
close() {
|
|
879
1003
|
return __async(this, null, function* () {
|
|
880
1004
|
this.isDestroyed = true;
|
|
881
|
-
if (this.isConnectionManaged && typeof this.sqlite.close ===
|
|
1005
|
+
if (this.isConnectionManaged && typeof this.sqlite.close === 'function') {
|
|
882
1006
|
this.sqlite.close();
|
|
883
1007
|
}
|
|
884
1008
|
});
|
|
@@ -891,12 +1015,14 @@ var SQLiteRateLimitStore = class {
|
|
|
891
1015
|
}
|
|
892
1016
|
cleanupExpiredRequests(resource, windowStart) {
|
|
893
1017
|
return __async(this, null, function* () {
|
|
894
|
-
yield this.db
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
1018
|
+
yield this.db
|
|
1019
|
+
.delete(rateLimitTable)
|
|
1020
|
+
.where(
|
|
1021
|
+
and(
|
|
1022
|
+
eq(rateLimitTable.resource, resource),
|
|
1023
|
+
lt(rateLimitTable.timestamp, windowStart),
|
|
1024
|
+
),
|
|
1025
|
+
);
|
|
900
1026
|
});
|
|
901
1027
|
}
|
|
902
1028
|
initializeDatabase() {
|
|
@@ -917,15 +1043,15 @@ var SQLiteRateLimitStore = class {
|
|
|
917
1043
|
};
|
|
918
1044
|
var DEFAULT_RATE_LIMIT2 = {
|
|
919
1045
|
limit: 200,
|
|
920
|
-
windowMs: 36e5
|
|
1046
|
+
windowMs: 36e5,
|
|
921
1047
|
// 1 hour
|
|
922
1048
|
};
|
|
923
1049
|
var SqliteAdaptiveRateLimitStore = class {
|
|
924
1050
|
constructor({
|
|
925
|
-
database =
|
|
1051
|
+
database = ':memory:',
|
|
926
1052
|
defaultConfig = DEFAULT_RATE_LIMIT2,
|
|
927
1053
|
resourceConfigs = /* @__PURE__ */ new Map(),
|
|
928
|
-
adaptiveConfig = {}
|
|
1054
|
+
adaptiveConfig = {},
|
|
929
1055
|
} = {}) {
|
|
930
1056
|
/** Indicates whether this store manages (and should close) the SQLite connection */
|
|
931
1057
|
this.isConnectionManaged = false;
|
|
@@ -936,7 +1062,7 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
936
1062
|
this.cachedCapacity = /* @__PURE__ */ new Map();
|
|
937
1063
|
let sqliteInstance;
|
|
938
1064
|
let isConnectionManaged = false;
|
|
939
|
-
if (typeof database ===
|
|
1065
|
+
if (typeof database === 'string') {
|
|
940
1066
|
sqliteInstance = new Database(database);
|
|
941
1067
|
isConnectionManaged = true;
|
|
942
1068
|
} else {
|
|
@@ -950,33 +1076,33 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
950
1076
|
this.capacityCalculator = new AdaptiveCapacityCalculator(adaptiveConfig);
|
|
951
1077
|
this.initializeDatabase();
|
|
952
1078
|
}
|
|
953
|
-
canProceed(resource, priority =
|
|
1079
|
+
canProceed(resource, priority = 'background') {
|
|
954
1080
|
return __async(this, null, function* () {
|
|
955
1081
|
if (this.isDestroyed) {
|
|
956
|
-
throw new Error(
|
|
1082
|
+
throw new Error('Rate limit store has been destroyed');
|
|
957
1083
|
}
|
|
958
1084
|
yield this.ensureActivityMetrics(resource);
|
|
959
1085
|
const metrics = this.getOrCreateActivityMetrics(resource);
|
|
960
1086
|
const capacity = this.calculateCurrentCapacity(resource, metrics);
|
|
961
|
-
if (priority ===
|
|
1087
|
+
if (priority === 'background' && capacity.backgroundPaused) {
|
|
962
1088
|
return false;
|
|
963
1089
|
}
|
|
964
|
-
const currentUserRequests = yield this.getCurrentUsage(resource,
|
|
1090
|
+
const currentUserRequests = yield this.getCurrentUsage(resource, 'user');
|
|
965
1091
|
const currentBackgroundRequests = yield this.getCurrentUsage(
|
|
966
1092
|
resource,
|
|
967
|
-
|
|
1093
|
+
'background',
|
|
968
1094
|
);
|
|
969
|
-
if (priority ===
|
|
1095
|
+
if (priority === 'user') {
|
|
970
1096
|
return currentUserRequests < capacity.userReserved;
|
|
971
1097
|
} else {
|
|
972
1098
|
return currentBackgroundRequests < capacity.backgroundMax;
|
|
973
1099
|
}
|
|
974
1100
|
});
|
|
975
1101
|
}
|
|
976
|
-
record(resource, priority =
|
|
1102
|
+
record(resource, priority = 'background') {
|
|
977
1103
|
return __async(this, null, function* () {
|
|
978
1104
|
if (this.isDestroyed) {
|
|
979
|
-
throw new Error(
|
|
1105
|
+
throw new Error('Rate limit store has been destroyed');
|
|
980
1106
|
}
|
|
981
1107
|
const now = Date.now();
|
|
982
1108
|
this.db.run(sql`
|
|
@@ -984,34 +1110,38 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
984
1110
|
VALUES (${resource}, ${now}, ${priority})
|
|
985
1111
|
`);
|
|
986
1112
|
const metrics = this.getOrCreateActivityMetrics(resource);
|
|
987
|
-
if (priority ===
|
|
1113
|
+
if (priority === 'user') {
|
|
988
1114
|
metrics.recentUserRequests.push(now);
|
|
989
1115
|
this.cleanupOldRequests(metrics.recentUserRequests);
|
|
990
1116
|
} else {
|
|
991
1117
|
metrics.recentBackgroundRequests.push(now);
|
|
992
1118
|
this.cleanupOldRequests(metrics.recentBackgroundRequests);
|
|
993
1119
|
}
|
|
994
|
-
metrics.userActivityTrend =
|
|
995
|
-
|
|
996
|
-
|
|
1120
|
+
metrics.userActivityTrend =
|
|
1121
|
+
this.capacityCalculator.calculateActivityTrend(
|
|
1122
|
+
metrics.recentUserRequests,
|
|
1123
|
+
);
|
|
997
1124
|
});
|
|
998
1125
|
}
|
|
999
1126
|
getStatus(resource) {
|
|
1000
1127
|
return __async(this, null, function* () {
|
|
1001
1128
|
if (this.isDestroyed) {
|
|
1002
|
-
throw new Error(
|
|
1129
|
+
throw new Error('Rate limit store has been destroyed');
|
|
1003
1130
|
}
|
|
1004
1131
|
yield this.ensureActivityMetrics(resource);
|
|
1005
1132
|
const metrics = this.getOrCreateActivityMetrics(resource);
|
|
1006
1133
|
const capacity = this.calculateCurrentCapacity(resource, metrics);
|
|
1007
|
-
const currentUserUsage = yield this.getCurrentUsage(resource,
|
|
1134
|
+
const currentUserUsage = yield this.getCurrentUsage(resource, 'user');
|
|
1008
1135
|
const currentBackgroundUsage = yield this.getCurrentUsage(
|
|
1009
1136
|
resource,
|
|
1010
|
-
|
|
1137
|
+
'background',
|
|
1011
1138
|
);
|
|
1012
1139
|
const config = this.resourceConfigs.get(resource) || this.defaultConfig;
|
|
1013
1140
|
return {
|
|
1014
|
-
remaining:
|
|
1141
|
+
remaining:
|
|
1142
|
+
capacity.userReserved -
|
|
1143
|
+
currentUserUsage +
|
|
1144
|
+
(capacity.backgroundMax - currentBackgroundUsage),
|
|
1015
1145
|
resetTime: new Date(Date.now() + config.windowMs),
|
|
1016
1146
|
limit: this.getResourceLimit(resource),
|
|
1017
1147
|
adaptive: {
|
|
@@ -1019,28 +1149,30 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1019
1149
|
backgroundMax: capacity.backgroundMax,
|
|
1020
1150
|
backgroundPaused: capacity.backgroundPaused,
|
|
1021
1151
|
recentUserActivity: this.capacityCalculator.getRecentActivity(
|
|
1022
|
-
metrics.recentUserRequests
|
|
1152
|
+
metrics.recentUserRequests,
|
|
1023
1153
|
),
|
|
1024
|
-
reason: capacity.reason
|
|
1025
|
-
}
|
|
1154
|
+
reason: capacity.reason,
|
|
1155
|
+
},
|
|
1026
1156
|
};
|
|
1027
1157
|
});
|
|
1028
1158
|
}
|
|
1029
1159
|
reset(resource) {
|
|
1030
1160
|
return __async(this, null, function* () {
|
|
1031
1161
|
if (this.isDestroyed) {
|
|
1032
|
-
throw new Error(
|
|
1162
|
+
throw new Error('Rate limit store has been destroyed');
|
|
1033
1163
|
}
|
|
1034
|
-
yield this.db
|
|
1164
|
+
yield this.db
|
|
1165
|
+
.delete(rateLimitTable)
|
|
1166
|
+
.where(eq(rateLimitTable.resource, resource));
|
|
1035
1167
|
this.activityMetrics.delete(resource);
|
|
1036
1168
|
this.cachedCapacity.delete(resource);
|
|
1037
1169
|
this.lastCapacityUpdate.delete(resource);
|
|
1038
1170
|
});
|
|
1039
1171
|
}
|
|
1040
|
-
getWaitTime(resource, priority =
|
|
1172
|
+
getWaitTime(resource, priority = 'background') {
|
|
1041
1173
|
return __async(this, null, function* () {
|
|
1042
1174
|
if (this.isDestroyed) {
|
|
1043
|
-
throw new Error(
|
|
1175
|
+
throw new Error('Rate limit store has been destroyed');
|
|
1044
1176
|
}
|
|
1045
1177
|
const config = this.resourceConfigs.get(resource) || this.defaultConfig;
|
|
1046
1178
|
if (config.limit === 0) {
|
|
@@ -1053,20 +1185,22 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1053
1185
|
yield this.ensureActivityMetrics(resource);
|
|
1054
1186
|
const metrics = this.getOrCreateActivityMetrics(resource);
|
|
1055
1187
|
const capacity = this.calculateCurrentCapacity(resource, metrics);
|
|
1056
|
-
if (priority ===
|
|
1188
|
+
if (priority === 'background' && capacity.backgroundPaused) {
|
|
1057
1189
|
return this.capacityCalculator.config.recalculationIntervalMs;
|
|
1058
1190
|
}
|
|
1059
1191
|
const now = Date.now();
|
|
1060
1192
|
const windowStart = now - config.windowMs;
|
|
1061
|
-
const oldestResult = this.sqlite
|
|
1062
|
-
|
|
1193
|
+
const oldestResult = this.sqlite
|
|
1194
|
+
.prepare(
|
|
1195
|
+
`
|
|
1063
1196
|
SELECT timestamp
|
|
1064
1197
|
FROM rate_limits
|
|
1065
1198
|
WHERE resource = ? AND COALESCE(priority, 'background') = ? AND timestamp >= ?
|
|
1066
1199
|
ORDER BY timestamp
|
|
1067
1200
|
LIMIT 1
|
|
1068
|
-
|
|
1069
|
-
|
|
1201
|
+
`,
|
|
1202
|
+
)
|
|
1203
|
+
.get(resource, priority, windowStart);
|
|
1070
1204
|
if (!oldestResult) {
|
|
1071
1205
|
return 0;
|
|
1072
1206
|
}
|
|
@@ -1097,10 +1231,15 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1097
1231
|
return __async(this, null, function* () {
|
|
1098
1232
|
var _a;
|
|
1099
1233
|
if (this.isDestroyed) {
|
|
1100
|
-
throw new Error(
|
|
1101
|
-
}
|
|
1102
|
-
const totalResult = yield this.db
|
|
1103
|
-
|
|
1234
|
+
throw new Error('Rate limit store has been destroyed');
|
|
1235
|
+
}
|
|
1236
|
+
const totalResult = yield this.db
|
|
1237
|
+
.select({ count: count() })
|
|
1238
|
+
.from(rateLimitTable);
|
|
1239
|
+
const resourcesResult = yield this.db
|
|
1240
|
+
.select({ resource: rateLimitTable.resource })
|
|
1241
|
+
.from(rateLimitTable)
|
|
1242
|
+
.groupBy(rateLimitTable.resource);
|
|
1104
1243
|
const uniqueResources = resourcesResult.length;
|
|
1105
1244
|
const rateLimitedResources = [];
|
|
1106
1245
|
for (const { resource } of resourcesResult) {
|
|
@@ -1112,7 +1251,7 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1112
1251
|
return {
|
|
1113
1252
|
totalRequests: ((_a = totalResult[0]) == null ? void 0 : _a.count) || 0,
|
|
1114
1253
|
uniqueResources,
|
|
1115
|
-
rateLimitedResources
|
|
1254
|
+
rateLimitedResources,
|
|
1116
1255
|
};
|
|
1117
1256
|
});
|
|
1118
1257
|
}
|
|
@@ -1122,7 +1261,7 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1122
1261
|
clear() {
|
|
1123
1262
|
return __async(this, null, function* () {
|
|
1124
1263
|
if (this.isDestroyed) {
|
|
1125
|
-
throw new Error(
|
|
1264
|
+
throw new Error('Rate limit store has been destroyed');
|
|
1126
1265
|
}
|
|
1127
1266
|
yield this.db.delete(rateLimitTable);
|
|
1128
1267
|
this.activityMetrics.clear();
|
|
@@ -1136,7 +1275,10 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1136
1275
|
cleanup() {
|
|
1137
1276
|
return __async(this, null, function* () {
|
|
1138
1277
|
const now = Date.now();
|
|
1139
|
-
const resources = yield this.db
|
|
1278
|
+
const resources = yield this.db
|
|
1279
|
+
.select({ resource: rateLimitTable.resource })
|
|
1280
|
+
.from(rateLimitTable)
|
|
1281
|
+
.groupBy(rateLimitTable.resource);
|
|
1140
1282
|
for (const { resource } of resources) {
|
|
1141
1283
|
const config = this.resourceConfigs.get(resource) || this.defaultConfig;
|
|
1142
1284
|
const windowStart = now - config.windowMs;
|
|
@@ -1150,7 +1292,7 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1150
1292
|
close() {
|
|
1151
1293
|
return __async(this, null, function* () {
|
|
1152
1294
|
this.isDestroyed = true;
|
|
1153
|
-
if (this.isConnectionManaged && typeof this.sqlite.close ===
|
|
1295
|
+
if (this.isConnectionManaged && typeof this.sqlite.close === 'function') {
|
|
1154
1296
|
this.sqlite.close();
|
|
1155
1297
|
}
|
|
1156
1298
|
});
|
|
@@ -1164,15 +1306,18 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1164
1306
|
// Private helper methods for adaptive functionality
|
|
1165
1307
|
calculateCurrentCapacity(resource, metrics) {
|
|
1166
1308
|
const lastUpdate = this.lastCapacityUpdate.get(resource) || 0;
|
|
1167
|
-
const recalcInterval =
|
|
1309
|
+
const recalcInterval =
|
|
1310
|
+
this.capacityCalculator.config.recalculationIntervalMs;
|
|
1168
1311
|
if (Date.now() - lastUpdate < recalcInterval) {
|
|
1169
|
-
return
|
|
1312
|
+
return (
|
|
1313
|
+
this.cachedCapacity.get(resource) || this.getDefaultCapacity(resource)
|
|
1314
|
+
);
|
|
1170
1315
|
}
|
|
1171
1316
|
const totalLimit = this.getResourceLimit(resource);
|
|
1172
1317
|
const capacity = this.capacityCalculator.calculateDynamicCapacity(
|
|
1173
1318
|
resource,
|
|
1174
1319
|
totalLimit,
|
|
1175
|
-
metrics
|
|
1320
|
+
metrics,
|
|
1176
1321
|
);
|
|
1177
1322
|
this.cachedCapacity.set(resource, capacity);
|
|
1178
1323
|
this.lastCapacityUpdate.set(resource, Date.now());
|
|
@@ -1183,7 +1328,7 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1183
1328
|
this.activityMetrics.set(resource, {
|
|
1184
1329
|
recentUserRequests: [],
|
|
1185
1330
|
recentBackgroundRequests: [],
|
|
1186
|
-
userActivityTrend:
|
|
1331
|
+
userActivityTrend: 'none',
|
|
1187
1332
|
});
|
|
1188
1333
|
}
|
|
1189
1334
|
return this.activityMetrics.get(resource);
|
|
@@ -1194,30 +1339,34 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1194
1339
|
return;
|
|
1195
1340
|
}
|
|
1196
1341
|
const now = Date.now();
|
|
1197
|
-
const windowStart =
|
|
1198
|
-
|
|
1199
|
-
|
|
1342
|
+
const windowStart =
|
|
1343
|
+
now - this.capacityCalculator.config.monitoringWindowMs;
|
|
1344
|
+
const recentRequests = this.sqlite
|
|
1345
|
+
.prepare(
|
|
1346
|
+
`
|
|
1200
1347
|
SELECT timestamp, COALESCE(priority, 'background') as priority
|
|
1201
1348
|
FROM rate_limits
|
|
1202
1349
|
WHERE resource = ? AND timestamp >= ?
|
|
1203
1350
|
ORDER BY timestamp
|
|
1204
|
-
|
|
1205
|
-
|
|
1351
|
+
`,
|
|
1352
|
+
)
|
|
1353
|
+
.all(resource, windowStart);
|
|
1206
1354
|
const metrics = {
|
|
1207
1355
|
recentUserRequests: [],
|
|
1208
1356
|
recentBackgroundRequests: [],
|
|
1209
|
-
userActivityTrend:
|
|
1357
|
+
userActivityTrend: 'none',
|
|
1210
1358
|
};
|
|
1211
1359
|
for (const request of recentRequests) {
|
|
1212
|
-
if (request.priority ===
|
|
1360
|
+
if (request.priority === 'user') {
|
|
1213
1361
|
metrics.recentUserRequests.push(request.timestamp);
|
|
1214
1362
|
} else {
|
|
1215
1363
|
metrics.recentBackgroundRequests.push(request.timestamp);
|
|
1216
1364
|
}
|
|
1217
1365
|
}
|
|
1218
|
-
metrics.userActivityTrend =
|
|
1219
|
-
|
|
1220
|
-
|
|
1366
|
+
metrics.userActivityTrend =
|
|
1367
|
+
this.capacityCalculator.calculateActivityTrend(
|
|
1368
|
+
metrics.recentUserRequests,
|
|
1369
|
+
);
|
|
1221
1370
|
this.activityMetrics.set(resource, metrics);
|
|
1222
1371
|
});
|
|
1223
1372
|
}
|
|
@@ -1227,18 +1376,21 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1227
1376
|
const now = Date.now();
|
|
1228
1377
|
const windowStart = now - config.windowMs;
|
|
1229
1378
|
yield this.cleanupExpiredRequests(resource, windowStart);
|
|
1230
|
-
const result = this.sqlite
|
|
1231
|
-
|
|
1379
|
+
const result = this.sqlite
|
|
1380
|
+
.prepare(
|
|
1381
|
+
`
|
|
1232
1382
|
SELECT COUNT(*) as count
|
|
1233
1383
|
FROM rate_limits
|
|
1234
1384
|
WHERE resource = ? AND priority = ? AND timestamp >= ?
|
|
1235
|
-
|
|
1236
|
-
|
|
1385
|
+
`,
|
|
1386
|
+
)
|
|
1387
|
+
.get(resource, priority, windowStart);
|
|
1237
1388
|
return result.count || 0;
|
|
1238
1389
|
});
|
|
1239
1390
|
}
|
|
1240
1391
|
cleanupOldRequests(requests) {
|
|
1241
|
-
const cutoff =
|
|
1392
|
+
const cutoff =
|
|
1393
|
+
Date.now() - this.capacityCalculator.config.monitoringWindowMs;
|
|
1242
1394
|
while (requests.length > 0 && requests[0] < cutoff) {
|
|
1243
1395
|
requests.shift();
|
|
1244
1396
|
}
|
|
@@ -1253,17 +1405,19 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1253
1405
|
userReserved: Math.floor(limit * 0.3),
|
|
1254
1406
|
backgroundMax: Math.floor(limit * 0.7),
|
|
1255
1407
|
backgroundPaused: false,
|
|
1256
|
-
reason:
|
|
1408
|
+
reason: 'Default capacity allocation',
|
|
1257
1409
|
};
|
|
1258
1410
|
}
|
|
1259
1411
|
cleanupExpiredRequests(resource, windowStart) {
|
|
1260
1412
|
return __async(this, null, function* () {
|
|
1261
|
-
yield this.db
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1413
|
+
yield this.db
|
|
1414
|
+
.delete(rateLimitTable)
|
|
1415
|
+
.where(
|
|
1416
|
+
and(
|
|
1417
|
+
eq(rateLimitTable.resource, resource),
|
|
1418
|
+
lt(rateLimitTable.timestamp, windowStart),
|
|
1419
|
+
),
|
|
1420
|
+
);
|
|
1267
1421
|
});
|
|
1268
1422
|
}
|
|
1269
1423
|
initializeDatabase() {
|
|
@@ -1279,8 +1433,7 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1279
1433
|
this.db.run(sql`
|
|
1280
1434
|
ALTER TABLE rate_limits ADD COLUMN priority TEXT DEFAULT 'background'
|
|
1281
1435
|
`);
|
|
1282
|
-
} catch (e) {
|
|
1283
|
-
}
|
|
1436
|
+
} catch (e) {}
|
|
1284
1437
|
this.db.run(sql`
|
|
1285
1438
|
CREATE INDEX IF NOT EXISTS idx_rate_limit_resource ON rate_limits(resource)
|
|
1286
1439
|
`);
|
|
@@ -1294,6 +1447,14 @@ var SqliteAdaptiveRateLimitStore = class {
|
|
|
1294
1447
|
}
|
|
1295
1448
|
};
|
|
1296
1449
|
|
|
1297
|
-
export {
|
|
1450
|
+
export {
|
|
1451
|
+
SQLiteCacheStore,
|
|
1452
|
+
SQLiteDedupeStore,
|
|
1453
|
+
SQLiteRateLimitStore,
|
|
1454
|
+
SqliteAdaptiveRateLimitStore,
|
|
1455
|
+
cacheTable,
|
|
1456
|
+
dedupeTable,
|
|
1457
|
+
rateLimitTable,
|
|
1458
|
+
};
|
|
1459
|
+
//# sourceMappingURL=index.js.map
|
|
1298
1460
|
//# sourceMappingURL=index.js.map
|
|
1299
|
-
//# sourceMappingURL=index.js.map
|