@workglow/storage 0.2.26 → 0.2.27
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/browser.js +218 -12
- package/dist/browser.js.map +13 -13
- package/dist/bun.js +703 -24
- package/dist/bun.js.map +18 -17
- package/dist/common-server.d.ts +1 -0
- package/dist/common-server.d.ts.map +1 -1
- package/dist/node.js +703 -24
- package/dist/node.js.map +18 -17
- package/dist/queue/IQueueStorage.d.ts +25 -2
- package/dist/queue/IQueueStorage.d.ts.map +1 -1
- package/dist/queue/InMemoryQueueStorage.d.ts +1 -0
- package/dist/queue/InMemoryQueueStorage.d.ts.map +1 -1
- package/dist/queue/IndexedDbQueueStorage.d.ts +1 -0
- package/dist/queue/IndexedDbQueueStorage.d.ts.map +1 -1
- package/dist/queue/PostgresQueueStorage.d.ts +24 -3
- package/dist/queue/PostgresQueueStorage.d.ts.map +1 -1
- package/dist/queue/SqliteQueueStorage.d.ts +8 -0
- package/dist/queue/SqliteQueueStorage.d.ts.map +1 -1
- package/dist/queue/SupabaseQueueStorage.d.ts +1 -0
- package/dist/queue/SupabaseQueueStorage.d.ts.map +1 -1
- package/dist/queue/TelemetryQueueStorage.d.ts +2 -1
- package/dist/queue/TelemetryQueueStorage.d.ts.map +1 -1
- package/dist/queue-limiter/IRateLimiterStorage.d.ts +46 -0
- package/dist/queue-limiter/IRateLimiterStorage.d.ts.map +1 -1
- package/dist/queue-limiter/InMemoryRateLimiterStorage.d.ts +12 -1
- package/dist/queue-limiter/InMemoryRateLimiterStorage.d.ts.map +1 -1
- package/dist/queue-limiter/IndexedDbRateLimiterStorage.d.ts +28 -1
- package/dist/queue-limiter/IndexedDbRateLimiterStorage.d.ts.map +1 -1
- package/dist/queue-limiter/PostgresRateLimiterStorage.d.ts +4 -1
- package/dist/queue-limiter/PostgresRateLimiterStorage.d.ts.map +1 -1
- package/dist/queue-limiter/SqliteRateLimiterStorage.d.ts +10 -1
- package/dist/queue-limiter/SqliteRateLimiterStorage.d.ts.map +1 -1
- package/dist/queue-limiter/SupabaseRateLimiterStorage.d.ts +6 -1
- package/dist/queue-limiter/SupabaseRateLimiterStorage.d.ts.map +1 -1
- package/dist/tabular/IndexedDbTabularStorage.d.ts.map +1 -1
- package/dist/tabular/SharedInMemoryTabularStorage.d.ts +2 -1
- package/dist/tabular/SharedInMemoryTabularStorage.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/browser.js
CHANGED
|
@@ -1574,6 +1574,7 @@ var IN_MEMORY_QUEUE_STORAGE = createServiceToken9("jobqueue.storage.inMemory");
|
|
|
1574
1574
|
|
|
1575
1575
|
class InMemoryQueueStorage {
|
|
1576
1576
|
queueName;
|
|
1577
|
+
scope = "process";
|
|
1577
1578
|
prefixValues;
|
|
1578
1579
|
events = new EventEmitter3;
|
|
1579
1580
|
constructor(queueName, options) {
|
|
@@ -1783,6 +1784,9 @@ class TelemetryQueueStorage {
|
|
|
1783
1784
|
this.storageName = storageName;
|
|
1784
1785
|
this.inner = inner;
|
|
1785
1786
|
}
|
|
1787
|
+
get scope() {
|
|
1788
|
+
return this.inner.scope;
|
|
1789
|
+
}
|
|
1786
1790
|
add(job) {
|
|
1787
1791
|
return traced("workglow.storage.queue.add", this.storageName, () => this.inner.add(job));
|
|
1788
1792
|
}
|
|
@@ -1833,13 +1837,15 @@ class TelemetryQueueStorage {
|
|
|
1833
1837
|
}
|
|
1834
1838
|
}
|
|
1835
1839
|
// src/queue-limiter/InMemoryRateLimiterStorage.ts
|
|
1836
|
-
import { createServiceToken as createServiceToken10, sleep as sleep2 } from "@workglow/util";
|
|
1840
|
+
import { createServiceToken as createServiceToken10, sleep as sleep2, uuid4 as uuid43 } from "@workglow/util";
|
|
1837
1841
|
var IN_MEMORY_RATE_LIMITER_STORAGE = createServiceToken10("ratelimiter.storage.inMemory");
|
|
1838
1842
|
|
|
1839
1843
|
class InMemoryRateLimiterStorage {
|
|
1844
|
+
scope = "process";
|
|
1840
1845
|
prefixValues;
|
|
1841
1846
|
executions = new Map;
|
|
1842
1847
|
nextAvailableTimes = new Map;
|
|
1848
|
+
reserveChains = new Map;
|
|
1843
1849
|
constructor(options) {
|
|
1844
1850
|
this.prefixValues = options?.prefixValues ?? {};
|
|
1845
1851
|
}
|
|
@@ -1848,11 +1854,67 @@ class InMemoryRateLimiterStorage {
|
|
|
1848
1854
|
return prefixPart ? `${prefixPart}|${queueName}` : queueName;
|
|
1849
1855
|
}
|
|
1850
1856
|
async setupDatabase() {}
|
|
1857
|
+
async withKeyLock(key, fn) {
|
|
1858
|
+
const previous = this.reserveChains.get(key) ?? Promise.resolve();
|
|
1859
|
+
let release;
|
|
1860
|
+
const next = new Promise((resolve) => {
|
|
1861
|
+
release = resolve;
|
|
1862
|
+
});
|
|
1863
|
+
this.reserveChains.set(key, next);
|
|
1864
|
+
try {
|
|
1865
|
+
await previous;
|
|
1866
|
+
return await fn();
|
|
1867
|
+
} finally {
|
|
1868
|
+
release(undefined);
|
|
1869
|
+
if (this.reserveChains.get(key) === next) {
|
|
1870
|
+
this.reserveChains.delete(key);
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
async tryReserveExecution(queueName, maxExecutions, windowMs) {
|
|
1875
|
+
const key = this.makeKey(queueName);
|
|
1876
|
+
return this.withKeyLock(key, () => {
|
|
1877
|
+
const now = Date.now();
|
|
1878
|
+
const windowStart = new Date(now - windowMs);
|
|
1879
|
+
const executions = this.executions.get(key) ?? [];
|
|
1880
|
+
const live = executions.filter((e) => e.executedAt > windowStart);
|
|
1881
|
+
if (live.length >= maxExecutions) {
|
|
1882
|
+
if (live.length !== executions.length) {
|
|
1883
|
+
this.executions.set(key, live);
|
|
1884
|
+
}
|
|
1885
|
+
return null;
|
|
1886
|
+
}
|
|
1887
|
+
const next = this.nextAvailableTimes.get(key);
|
|
1888
|
+
if (next && next.getTime() > now) {
|
|
1889
|
+
return null;
|
|
1890
|
+
}
|
|
1891
|
+
const id = uuid43();
|
|
1892
|
+
live.push({ id, queueName, executedAt: new Date(now) });
|
|
1893
|
+
this.executions.set(key, live);
|
|
1894
|
+
return id;
|
|
1895
|
+
});
|
|
1896
|
+
}
|
|
1897
|
+
async releaseExecution(queueName, token) {
|
|
1898
|
+
if (token === null || token === undefined)
|
|
1899
|
+
return;
|
|
1900
|
+
const key = this.makeKey(queueName);
|
|
1901
|
+
await this.withKeyLock(key, () => {
|
|
1902
|
+
const executions = this.executions.get(key);
|
|
1903
|
+
if (!executions || executions.length === 0)
|
|
1904
|
+
return;
|
|
1905
|
+
const idx = executions.findIndex((e) => e.id === token);
|
|
1906
|
+
if (idx === -1)
|
|
1907
|
+
return;
|
|
1908
|
+
executions.splice(idx, 1);
|
|
1909
|
+
this.executions.set(key, executions);
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1851
1912
|
async recordExecution(queueName) {
|
|
1852
1913
|
await sleep2(0);
|
|
1853
1914
|
const key = this.makeKey(queueName);
|
|
1854
1915
|
const executions = this.executions.get(key) ?? [];
|
|
1855
1916
|
executions.push({
|
|
1917
|
+
id: uuid43(),
|
|
1856
1918
|
queueName,
|
|
1857
1919
|
executedAt: new Date
|
|
1858
1920
|
});
|
|
@@ -2434,7 +2496,7 @@ class LazyEncryptedCredentialStore {
|
|
|
2434
2496
|
}
|
|
2435
2497
|
}
|
|
2436
2498
|
// src/tabular/IndexedDbTabularStorage.ts
|
|
2437
|
-
import { createServiceToken as createServiceToken12, deepEqual as deepEqual2, makeFingerprint as makeFingerprint5, uuid4 as
|
|
2499
|
+
import { createServiceToken as createServiceToken12, deepEqual as deepEqual2, makeFingerprint as makeFingerprint5, uuid4 as uuid44 } from "@workglow/util";
|
|
2438
2500
|
|
|
2439
2501
|
// src/util/IndexedDbTable.ts
|
|
2440
2502
|
import { deepEqual } from "@workglow/util";
|
|
@@ -2825,7 +2887,7 @@ class IndexedDbTabularStorage extends BaseTabularStorage {
|
|
|
2825
2887
|
}
|
|
2826
2888
|
generateKeyValue(columnName, strategy) {
|
|
2827
2889
|
if (strategy === "uuid") {
|
|
2828
|
-
return
|
|
2890
|
+
return uuid44();
|
|
2829
2891
|
}
|
|
2830
2892
|
throw new Error(`IndexedDB autoincrement keys are generated by the database, not client-side. Column: ${columnName}`);
|
|
2831
2893
|
}
|
|
@@ -3398,13 +3460,15 @@ class IndexedDbTabularStorage extends BaseTabularStorage {
|
|
|
3398
3460
|
}
|
|
3399
3461
|
let matches = true;
|
|
3400
3462
|
for (const [col, crit] of Object.entries(criteria)) {
|
|
3401
|
-
if (!isSearchCondition(crit))
|
|
3402
|
-
continue;
|
|
3403
3463
|
const pos = keyPathPositions.get(col);
|
|
3404
3464
|
if (pos === undefined)
|
|
3405
3465
|
continue;
|
|
3466
|
+
if (pos < prefix.length)
|
|
3467
|
+
continue;
|
|
3406
3468
|
const valFromKey = Array.isArray(key) ? key[pos] : key;
|
|
3407
|
-
|
|
3469
|
+
const op = isSearchCondition(crit) ? crit.operator : "=";
|
|
3470
|
+
const val = isSearchCondition(crit) ? crit.value : crit;
|
|
3471
|
+
if (!compareWithOperator(valFromKey, op, val)) {
|
|
3408
3472
|
matches = false;
|
|
3409
3473
|
break;
|
|
3410
3474
|
}
|
|
@@ -3651,6 +3715,9 @@ class SharedInMemoryTabularStorage extends BaseTabularStorage {
|
|
|
3651
3715
|
async query(criteria, options) {
|
|
3652
3716
|
return await this.inMemoryRepo.query(criteria, options);
|
|
3653
3717
|
}
|
|
3718
|
+
async queryIndex(criteria, options) {
|
|
3719
|
+
return await this.inMemoryRepo.queryIndex(criteria, options);
|
|
3720
|
+
}
|
|
3654
3721
|
async deleteSearch(criteria) {
|
|
3655
3722
|
await this.inMemoryRepo.deleteSearch(criteria);
|
|
3656
3723
|
this.broadcast({
|
|
@@ -4453,11 +4520,12 @@ class SupabaseKvStorage extends KvViaTabularStorage {
|
|
|
4453
4520
|
}
|
|
4454
4521
|
}
|
|
4455
4522
|
// src/queue/IndexedDbQueueStorage.ts
|
|
4456
|
-
import { createServiceToken as createServiceToken17, deepEqual as deepEqual3, makeFingerprint as makeFingerprint6, uuid4 as
|
|
4523
|
+
import { createServiceToken as createServiceToken17, deepEqual as deepEqual3, makeFingerprint as makeFingerprint6, uuid4 as uuid45 } from "@workglow/util";
|
|
4457
4524
|
var INDEXED_DB_QUEUE_STORAGE = createServiceToken17("jobqueue.storage.indexedDb");
|
|
4458
4525
|
|
|
4459
4526
|
class IndexedDbQueueStorage {
|
|
4460
4527
|
queueName;
|
|
4528
|
+
scope = "process";
|
|
4461
4529
|
db;
|
|
4462
4530
|
tableName;
|
|
4463
4531
|
migrationOptions;
|
|
@@ -4534,8 +4602,8 @@ class IndexedDbQueueStorage {
|
|
|
4534
4602
|
const db = await this.getDb();
|
|
4535
4603
|
const now = new Date().toISOString();
|
|
4536
4604
|
const jobWithPrefixes = job;
|
|
4537
|
-
jobWithPrefixes.id = jobWithPrefixes.id ??
|
|
4538
|
-
jobWithPrefixes.job_run_id = jobWithPrefixes.job_run_id ??
|
|
4605
|
+
jobWithPrefixes.id = jobWithPrefixes.id ?? uuid45();
|
|
4606
|
+
jobWithPrefixes.job_run_id = jobWithPrefixes.job_run_id ?? uuid45();
|
|
4539
4607
|
jobWithPrefixes.queue = this.queueName;
|
|
4540
4608
|
jobWithPrefixes.fingerprint = await makeFingerprint6(jobWithPrefixes.input);
|
|
4541
4609
|
jobWithPrefixes.status = JobStatus.PENDING;
|
|
@@ -5033,11 +5101,12 @@ class IndexedDbQueueStorage {
|
|
|
5033
5101
|
}
|
|
5034
5102
|
}
|
|
5035
5103
|
// src/queue/SupabaseQueueStorage.ts
|
|
5036
|
-
import { createServiceToken as createServiceToken18, deepEqual as deepEqual4, makeFingerprint as makeFingerprint7, uuid4 as
|
|
5104
|
+
import { createServiceToken as createServiceToken18, deepEqual as deepEqual4, makeFingerprint as makeFingerprint7, uuid4 as uuid46 } from "@workglow/util";
|
|
5037
5105
|
var SUPABASE_QUEUE_STORAGE = createServiceToken18("jobqueue.storage.supabase");
|
|
5038
5106
|
|
|
5039
5107
|
class SupabaseQueueStorage {
|
|
5040
5108
|
queueName;
|
|
5109
|
+
scope = "cluster";
|
|
5041
5110
|
client;
|
|
5042
5111
|
prefixes;
|
|
5043
5112
|
prefixValues;
|
|
@@ -5162,7 +5231,7 @@ class SupabaseQueueStorage {
|
|
|
5162
5231
|
async add(job) {
|
|
5163
5232
|
const now = new Date().toISOString();
|
|
5164
5233
|
job.queue = this.queueName;
|
|
5165
|
-
job.job_run_id = job.job_run_id ??
|
|
5234
|
+
job.job_run_id = job.job_run_id ?? uuid46();
|
|
5166
5235
|
job.fingerprint = await makeFingerprint7(job.input);
|
|
5167
5236
|
job.status = JobStatus.PENDING;
|
|
5168
5237
|
job.progress = 0;
|
|
@@ -5564,6 +5633,7 @@ import { createServiceToken as createServiceToken19 } from "@workglow/util";
|
|
|
5564
5633
|
var INDEXED_DB_RATE_LIMITER_STORAGE = createServiceToken19("ratelimiter.storage.indexedDb");
|
|
5565
5634
|
|
|
5566
5635
|
class IndexedDbRateLimiterStorage {
|
|
5636
|
+
scope = "process";
|
|
5567
5637
|
executionDb;
|
|
5568
5638
|
nextAvailableDb;
|
|
5569
5639
|
executionTableName;
|
|
@@ -5632,6 +5702,72 @@ class IndexedDbRateLimiterStorage {
|
|
|
5632
5702
|
];
|
|
5633
5703
|
this.nextAvailableDb = await ensureIndexedDbTable(this.nextAvailableTableName, buildKeyPath(["queue_name"]).join("_"), nextAvailableIndexes, this.migrationOptions);
|
|
5634
5704
|
}
|
|
5705
|
+
async tryReserveExecution(queueName, maxExecutions, windowMs) {
|
|
5706
|
+
const nextIso = await this.getNextAvailableTime(queueName);
|
|
5707
|
+
if (nextIso && new Date(nextIso).getTime() > Date.now()) {
|
|
5708
|
+
return null;
|
|
5709
|
+
}
|
|
5710
|
+
const execDb = await this.getExecutionDb();
|
|
5711
|
+
const prefixKeyValues = this.getPrefixKeyValues();
|
|
5712
|
+
const windowStartIso = new Date(Date.now() - windowMs).toISOString();
|
|
5713
|
+
const execTx = execDb.transaction(this.executionTableName, "readwrite");
|
|
5714
|
+
const execStore = execTx.objectStore(this.executionTableName);
|
|
5715
|
+
const insertedId = crypto.randomUUID();
|
|
5716
|
+
return new Promise((resolve, reject) => {
|
|
5717
|
+
let liveCount = 0;
|
|
5718
|
+
let didInsert = false;
|
|
5719
|
+
const liveRange = IDBKeyRange.bound([...prefixKeyValues, queueName, windowStartIso], [...prefixKeyValues, queueName, ""], true, false);
|
|
5720
|
+
const cursorReq = execStore.index("queue_executed_at").openCursor(liveRange);
|
|
5721
|
+
cursorReq.onsuccess = (event) => {
|
|
5722
|
+
const cursor = event.target.result;
|
|
5723
|
+
if (cursor) {
|
|
5724
|
+
const record2 = cursor.value;
|
|
5725
|
+
if (this.matchesPrefixes(record2)) {
|
|
5726
|
+
liveCount++;
|
|
5727
|
+
}
|
|
5728
|
+
cursor.continue();
|
|
5729
|
+
return;
|
|
5730
|
+
}
|
|
5731
|
+
if (liveCount >= maxExecutions) {
|
|
5732
|
+
execTx.abort();
|
|
5733
|
+
return;
|
|
5734
|
+
}
|
|
5735
|
+
const record = {
|
|
5736
|
+
id: insertedId,
|
|
5737
|
+
queue_name: queueName,
|
|
5738
|
+
executed_at: new Date().toISOString()
|
|
5739
|
+
};
|
|
5740
|
+
for (const [k, v] of Object.entries(this.prefixValues)) {
|
|
5741
|
+
record[k] = v;
|
|
5742
|
+
}
|
|
5743
|
+
const addReq = execStore.add(record);
|
|
5744
|
+
didInsert = true;
|
|
5745
|
+
addReq.onerror = () => {
|
|
5746
|
+
try {
|
|
5747
|
+
execTx.abort();
|
|
5748
|
+
} catch {}
|
|
5749
|
+
reject(addReq.error);
|
|
5750
|
+
};
|
|
5751
|
+
};
|
|
5752
|
+
cursorReq.onerror = () => reject(cursorReq.error);
|
|
5753
|
+
execTx.oncomplete = () => resolve(didInsert ? insertedId : null);
|
|
5754
|
+
execTx.onerror = () => reject(execTx.error);
|
|
5755
|
+
execTx.onabort = () => resolve(null);
|
|
5756
|
+
});
|
|
5757
|
+
}
|
|
5758
|
+
async releaseExecution(queueName, token) {
|
|
5759
|
+
if (token === null || token === undefined)
|
|
5760
|
+
return;
|
|
5761
|
+
const db = await this.getExecutionDb();
|
|
5762
|
+
const tx = db.transaction(this.executionTableName, "readwrite");
|
|
5763
|
+
const store = tx.objectStore(this.executionTableName);
|
|
5764
|
+
return new Promise((resolve, reject) => {
|
|
5765
|
+
const req = store.delete(token);
|
|
5766
|
+
req.onerror = () => reject(req.error);
|
|
5767
|
+
tx.oncomplete = () => resolve();
|
|
5768
|
+
tx.onerror = () => reject(tx.error);
|
|
5769
|
+
});
|
|
5770
|
+
}
|
|
5635
5771
|
async recordExecution(queueName) {
|
|
5636
5772
|
const db = await this.getExecutionDb();
|
|
5637
5773
|
const tx = db.transaction(this.executionTableName, "readwrite");
|
|
@@ -5785,6 +5921,7 @@ import { createServiceToken as createServiceToken20 } from "@workglow/util";
|
|
|
5785
5921
|
var SUPABASE_RATE_LIMITER_STORAGE = createServiceToken20("ratelimiter.storage.supabase");
|
|
5786
5922
|
|
|
5787
5923
|
class SupabaseRateLimiterStorage {
|
|
5924
|
+
scope = "cluster";
|
|
5788
5925
|
client;
|
|
5789
5926
|
prefixes;
|
|
5790
5927
|
prefixValues;
|
|
@@ -5867,6 +6004,75 @@ class SupabaseRateLimiterStorage {
|
|
|
5867
6004
|
if (nextTableError && nextTableError.code !== "42P07") {
|
|
5868
6005
|
throw nextTableError;
|
|
5869
6006
|
}
|
|
6007
|
+
const fnName = this.atomicReserveFunctionName();
|
|
6008
|
+
const prefixSig = this.prefixes.map((p) => `${p.name} ${this.getPrefixColumnType(p.type)}`).join(", ");
|
|
6009
|
+
const prefixSigPrefix = prefixSig ? prefixSig + ", " : "";
|
|
6010
|
+
const prefixWhere = this.prefixes.length > 0 ? " AND " + this.prefixes.map((p) => `${p.name} = _${p.name}`).join(" AND ") : "";
|
|
6011
|
+
const prefixInsertCols = this.prefixes.length > 0 ? this.prefixes.map((p) => p.name).join(", ") + ", " : "";
|
|
6012
|
+
const prefixInsertVals = this.prefixes.length > 0 ? this.prefixes.map((p) => `_${p.name}`).join(", ") + ", " : "";
|
|
6013
|
+
const lockKeyParts = [`'${this.executionTableName}'`, ...this.prefixes.map((p) => `_${p.name}::text`), `_queue_name::text`];
|
|
6014
|
+
const lockKeyExpr = `hashtextextended(${lockKeyParts.join(" || '|' || ")}, 0)`;
|
|
6015
|
+
const createFnSql = `
|
|
6016
|
+
CREATE OR REPLACE FUNCTION ${fnName}(
|
|
6017
|
+
${prefixSigPrefix}_queue_name TEXT, _window_start TIMESTAMPTZ, _max_exec INT
|
|
6018
|
+
) RETURNS BIGINT AS $fn$
|
|
6019
|
+
DECLARE
|
|
6020
|
+
_count INT;
|
|
6021
|
+
_next TIMESTAMPTZ;
|
|
6022
|
+
_new_id BIGINT;
|
|
6023
|
+
BEGIN
|
|
6024
|
+
PERFORM pg_advisory_xact_lock(${lockKeyExpr});
|
|
6025
|
+
SELECT COUNT(*) INTO _count FROM ${this.executionTableName}
|
|
6026
|
+
WHERE queue_name = _queue_name AND executed_at > _window_start${prefixWhere};
|
|
6027
|
+
IF _count >= _max_exec THEN RETURN NULL; END IF;
|
|
6028
|
+
SELECT next_available_at INTO _next FROM ${this.nextAvailableTableName}
|
|
6029
|
+
WHERE queue_name = _queue_name${prefixWhere};
|
|
6030
|
+
IF _next IS NOT NULL AND _next > NOW() THEN RETURN NULL; END IF;
|
|
6031
|
+
INSERT INTO ${this.executionTableName} (${prefixInsertCols}queue_name)
|
|
6032
|
+
VALUES (${prefixInsertVals}_queue_name)
|
|
6033
|
+
RETURNING id INTO _new_id;
|
|
6034
|
+
RETURN _new_id;
|
|
6035
|
+
END;
|
|
6036
|
+
$fn$ LANGUAGE plpgsql;
|
|
6037
|
+
`;
|
|
6038
|
+
const { error: fnError } = await this.client.rpc("exec_sql", { query: createFnSql });
|
|
6039
|
+
if (fnError) {
|
|
6040
|
+
throw fnError;
|
|
6041
|
+
}
|
|
6042
|
+
}
|
|
6043
|
+
atomicReserveFunctionName() {
|
|
6044
|
+
return `${this.executionTableName}_try_reserve`.slice(0, 63);
|
|
6045
|
+
}
|
|
6046
|
+
async tryReserveExecution(queueName, maxExecutions, windowMs) {
|
|
6047
|
+
const args = {
|
|
6048
|
+
_queue_name: queueName,
|
|
6049
|
+
_window_start: new Date(Date.now() - windowMs).toISOString(),
|
|
6050
|
+
_max_exec: maxExecutions
|
|
6051
|
+
};
|
|
6052
|
+
for (const p of this.prefixes) {
|
|
6053
|
+
args[`_${p.name}`] = this.prefixValues[p.name];
|
|
6054
|
+
}
|
|
6055
|
+
const { data, error } = await this.client.rpc(this.atomicReserveFunctionName(), args);
|
|
6056
|
+
if (error)
|
|
6057
|
+
throw error;
|
|
6058
|
+
if (data === null || data === undefined)
|
|
6059
|
+
return null;
|
|
6060
|
+
if (Array.isArray(data)) {
|
|
6061
|
+
if (data.length === 0)
|
|
6062
|
+
return null;
|
|
6063
|
+
const first = Object.values(data[0])[0];
|
|
6064
|
+
return first ?? null;
|
|
6065
|
+
}
|
|
6066
|
+
return data;
|
|
6067
|
+
}
|
|
6068
|
+
async releaseExecution(queueName, token) {
|
|
6069
|
+
if (token === null || token === undefined)
|
|
6070
|
+
return;
|
|
6071
|
+
let del = this.client.from(this.executionTableName).delete().eq("id", token).eq("queue_name", queueName);
|
|
6072
|
+
del = this.applyPrefixFilters(del);
|
|
6073
|
+
const { error: delError } = await del;
|
|
6074
|
+
if (delError)
|
|
6075
|
+
throw delError;
|
|
5870
6076
|
}
|
|
5871
6077
|
async recordExecution(queueName) {
|
|
5872
6078
|
const prefixInsertValues = this.getPrefixInsertValues();
|
|
@@ -6103,4 +6309,4 @@ export {
|
|
|
6103
6309
|
BaseTabularStorage
|
|
6104
6310
|
};
|
|
6105
6311
|
|
|
6106
|
-
//# debugId=
|
|
6312
|
+
//# debugId=E2D716C3197417F164756E2164756E21
|