gemi 0.93.0 → 0.95.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/FallbackProvider.d.ts +154 -0
- package/dist/ai/FallbackProvider.d.ts.map +1 -0
- package/dist/ai/index.d.ts +2 -0
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +12 -12
- package/dist/ai/index.js.map +4 -3
- package/dist/app/index.js +1 -1
- package/dist/bun/plugin.js +1 -1
- package/dist/bun/preload.js +1 -1
- package/dist/{chunk-g2xbpr8r.js → chunk-1hnpr3xt.js} +2 -2
- package/dist/{chunk-g2xbpr8r.js.map → chunk-1hnpr3xt.js.map} +1 -1
- package/dist/{chunk-v51a4g6w.js → chunk-2jse74pn.js} +2 -2
- package/dist/{chunk-v51a4g6w.js.map → chunk-2jse74pn.js.map} +1 -1
- package/dist/{chunk-1yt4hjqx.js → chunk-2shkf2gs.js} +2 -2
- package/dist/{chunk-1yt4hjqx.js.map → chunk-2shkf2gs.js.map} +1 -1
- package/dist/{chunk-dve6ryfd.js → chunk-2yyr5tdc.js} +1 -1
- package/dist/{chunk-4k4mh3gh.js → chunk-323715e8.js} +2 -2
- package/dist/{chunk-4k4mh3gh.js.map → chunk-323715e8.js.map} +1 -1
- package/dist/{chunk-xk4r9372.js → chunk-37jb6q13.js} +2 -2
- package/dist/{chunk-xk4r9372.js.map → chunk-37jb6q13.js.map} +1 -1
- package/dist/{chunk-wd9zab3e.js → chunk-38k1kjyb.js} +2 -2
- package/dist/{chunk-wd9zab3e.js.map → chunk-38k1kjyb.js.map} +1 -1
- package/dist/{chunk-aq1hjk00.js → chunk-3fjkbcra.js} +1 -1
- package/dist/{chunk-6qyc4e22.js → chunk-3fr22rtg.js} +2 -2
- package/dist/{chunk-6qyc4e22.js.map → chunk-3fr22rtg.js.map} +1 -1
- package/dist/{chunk-jj0ynn5t.js → chunk-56gce2z7.js} +2 -2
- package/dist/{chunk-jj0ynn5t.js.map → chunk-56gce2z7.js.map} +1 -1
- package/dist/{chunk-qs9drxja.js → chunk-5en4ydde.js} +2 -2
- package/dist/{chunk-qs9drxja.js.map → chunk-5en4ydde.js.map} +1 -1
- package/dist/{chunk-z10c81a9.js → chunk-5px4rkzf.js} +2 -2
- package/dist/{chunk-z10c81a9.js.map → chunk-5px4rkzf.js.map} +1 -1
- package/dist/{chunk-bb8e7rhf.js → chunk-7dnb21s9.js} +2 -2
- package/dist/{chunk-bb8e7rhf.js.map → chunk-7dnb21s9.js.map} +1 -1
- package/dist/chunk-7hfv5n00.js +5 -0
- package/dist/{chunk-cyze295m.js.map → chunk-7hfv5n00.js.map} +4 -3
- package/dist/{chunk-p0px3ym0.js → chunk-7kedxtbp.js} +2 -2
- package/dist/{chunk-p0px3ym0.js.map → chunk-7kedxtbp.js.map} +1 -1
- package/dist/{chunk-vpcys0ty.js → chunk-7ktsceyz.js} +2 -2
- package/dist/{chunk-vpcys0ty.js.map → chunk-7ktsceyz.js.map} +1 -1
- package/dist/{chunk-s22afmm9.js → chunk-7s5nh5mx.js} +2 -2
- package/dist/{chunk-s22afmm9.js.map → chunk-7s5nh5mx.js.map} +1 -1
- package/dist/{chunk-fz805r97.js → chunk-7vjbebst.js} +2 -2
- package/dist/{chunk-fz805r97.js.map → chunk-7vjbebst.js.map} +1 -1
- package/dist/{chunk-a1y7pa5z.js → chunk-8g99gnsd.js} +2 -2
- package/dist/{chunk-a1y7pa5z.js.map → chunk-8g99gnsd.js.map} +1 -1
- package/dist/{chunk-khvnm11p.js → chunk-9g5cpkkk.js} +2 -2
- package/dist/{chunk-khvnm11p.js.map → chunk-9g5cpkkk.js.map} +1 -1
- package/dist/{chunk-v6vsjdp7.js → chunk-9xf2fx98.js} +2 -2
- package/dist/{chunk-v6vsjdp7.js.map → chunk-9xf2fx98.js.map} +1 -1
- package/dist/{chunk-9pcsm8g3.js → chunk-adm5g1v8.js} +2 -2
- package/dist/{chunk-9pcsm8g3.js.map → chunk-adm5g1v8.js.map} +1 -1
- package/dist/{chunk-ej5mkm7t.js → chunk-b8m6zs7e.js} +2 -2
- package/dist/{chunk-ej5mkm7t.js.map → chunk-b8m6zs7e.js.map} +1 -1
- package/dist/{chunk-1wdfjmkx.js → chunk-bedkys40.js} +2 -2
- package/dist/{chunk-1wdfjmkx.js.map → chunk-bedkys40.js.map} +1 -1
- package/dist/chunk-bk4f99s4.js +5 -0
- package/dist/{chunk-svzdv2rf.js.map → chunk-bk4f99s4.js.map} +5 -5
- package/dist/chunk-br9p390p.js +5 -0
- package/dist/chunk-br9p390p.js.map +11 -0
- package/dist/chunk-dhe96f7z.js +5 -0
- package/dist/{chunk-4bh0maq0.js.map → chunk-dhe96f7z.js.map} +1 -1
- package/dist/{chunk-3prm2e2t.js → chunk-epwaxctc.js} +2 -2
- package/dist/{chunk-3prm2e2t.js.map → chunk-epwaxctc.js.map} +1 -1
- package/dist/{chunk-pwchwgkc.js → chunk-eqtsfvvd.js} +2 -2
- package/dist/{chunk-pwchwgkc.js.map → chunk-eqtsfvvd.js.map} +1 -1
- package/dist/{chunk-ffpm75zs.js → chunk-et6thczw.js} +2 -2
- package/dist/{chunk-ffpm75zs.js.map → chunk-et6thczw.js.map} +1 -1
- package/dist/{chunk-3m10ve1n.js → chunk-f6e2t4vb.js} +3 -3
- package/dist/{chunk-3m10ve1n.js.map → chunk-f6e2t4vb.js.map} +1 -1
- package/dist/{chunk-6ak8jfhm.js → chunk-f6veb369.js} +2 -2
- package/dist/{chunk-6ak8jfhm.js.map → chunk-f6veb369.js.map} +1 -1
- package/dist/{chunk-5y9jk4h4.js → chunk-fq03tz45.js} +2 -2
- package/dist/{chunk-5y9jk4h4.js.map → chunk-fq03tz45.js.map} +1 -1
- package/dist/{chunk-0rs8a7re.js → chunk-fyxp4bn0.js} +2 -2
- package/dist/{chunk-0rs8a7re.js.map → chunk-fyxp4bn0.js.map} +1 -1
- package/dist/{chunk-vbfwvyb8.js → chunk-ghz3e8b7.js} +2 -2
- package/dist/{chunk-vbfwvyb8.js.map → chunk-ghz3e8b7.js.map} +1 -1
- package/dist/{chunk-qrczhr16.js → chunk-h24rv10h.js} +2 -2
- package/dist/{chunk-qrczhr16.js.map → chunk-h24rv10h.js.map} +1 -1
- package/dist/{chunk-g6byqmdq.js → chunk-j2nx0dtq.js} +2 -2
- package/dist/{chunk-6xh4e55j.js.map → chunk-j2nx0dtq.js.map} +1 -1
- package/dist/chunk-j9x86xsc.js +19 -0
- package/dist/{chunk-g8tgp3ja.js.map → chunk-j9x86xsc.js.map} +4 -5
- package/dist/{chunk-7jshf4ms.js → chunk-jrp35qrk.js} +1 -1
- package/dist/{chunk-sppjqk4n.js → chunk-jxhznqhe.js} +3 -3
- package/dist/{chunk-sppjqk4n.js.map → chunk-jxhznqhe.js.map} +1 -1
- package/dist/{chunk-5v2rx0rk.js → chunk-kzh8bkg5.js} +2 -2
- package/dist/{chunk-5v2rx0rk.js.map → chunk-kzh8bkg5.js.map} +1 -1
- package/dist/{chunk-dwkhs81y.js → chunk-m3z60v9d.js} +2 -2
- package/dist/{chunk-dwkhs81y.js.map → chunk-m3z60v9d.js.map} +1 -1
- package/dist/{chunk-d869bd41.js → chunk-mekw2ap4.js} +2 -2
- package/dist/{chunk-d869bd41.js.map → chunk-mekw2ap4.js.map} +1 -1
- package/dist/{chunk-7k7a6h9j.js → chunk-mf936r5e.js} +2 -2
- package/dist/{chunk-7k7a6h9j.js.map → chunk-mf936r5e.js.map} +1 -1
- package/dist/{chunk-sqd77ksy.js → chunk-mym0zxxp.js} +3 -3
- package/dist/{chunk-sqd77ksy.js.map → chunk-mym0zxxp.js.map} +1 -1
- package/dist/{chunk-qv2sdxbq.js → chunk-n4807648.js} +3 -3
- package/dist/{chunk-qv2sdxbq.js.map → chunk-n4807648.js.map} +1 -1
- package/dist/{chunk-mmfstb0z.js → chunk-nfhy3sp8.js} +2 -2
- package/dist/{chunk-mmfstb0z.js.map → chunk-nfhy3sp8.js.map} +1 -1
- package/dist/{chunk-nvbbgbdk.js → chunk-nqabsqty.js} +4 -4
- package/dist/{chunk-nvbbgbdk.js.map → chunk-nqabsqty.js.map} +1 -1
- package/dist/{chunk-6xh4e55j.js → chunk-p3mdtnvv.js} +2 -2
- package/dist/{chunk-g6byqmdq.js.map → chunk-p3mdtnvv.js.map} +1 -1
- package/dist/{chunk-y3hdh6q6.js → chunk-qj5ts9d5.js} +2 -2
- package/dist/{chunk-y3hdh6q6.js.map → chunk-qj5ts9d5.js.map} +1 -1
- package/dist/{chunk-aawtyngp.js → chunk-qpek76vn.js} +3 -3
- package/dist/{chunk-aawtyngp.js.map → chunk-qpek76vn.js.map} +1 -1
- package/dist/{chunk-vryvdzmk.js → chunk-qqev9e50.js} +2 -2
- package/dist/{chunk-vryvdzmk.js.map → chunk-qqev9e50.js.map} +1 -1
- package/dist/{chunk-241aehp3.js → chunk-qxda7pzm.js} +2 -2
- package/dist/{chunk-241aehp3.js.map → chunk-qxda7pzm.js.map} +1 -1
- package/dist/{chunk-za1ncjh0.js → chunk-qz2p0hv5.js} +2 -2
- package/dist/{chunk-za1ncjh0.js.map → chunk-qz2p0hv5.js.map} +1 -1
- package/dist/{chunk-7bmctvep.js → chunk-safv6h9x.js} +2 -2
- package/dist/{chunk-7bmctvep.js.map → chunk-safv6h9x.js.map} +1 -1
- package/dist/{chunk-pgn3yh5k.js → chunk-ssqxzcad.js} +3 -3
- package/dist/{chunk-pgn3yh5k.js.map → chunk-ssqxzcad.js.map} +1 -1
- package/dist/{chunk-3jpetvsj.js → chunk-tcefqn3d.js} +2 -2
- package/dist/{chunk-3jpetvsj.js.map → chunk-tcefqn3d.js.map} +1 -1
- package/dist/{chunk-t328955a.js → chunk-twhf7w1x.js} +2 -2
- package/dist/{chunk-t328955a.js.map → chunk-twhf7w1x.js.map} +1 -1
- package/dist/{chunk-knw4t9e6.js → chunk-w98tp5fa.js} +2 -2
- package/dist/{chunk-knw4t9e6.js.map → chunk-w98tp5fa.js.map} +1 -1
- package/dist/{chunk-z405ks42.js → chunk-x24davqq.js} +2 -2
- package/dist/{chunk-z405ks42.js.map → chunk-x24davqq.js.map} +1 -1
- package/dist/{chunk-dmvrx8nm.js → chunk-xtqxy492.js} +3 -3
- package/dist/{chunk-dmvrx8nm.js.map → chunk-xtqxy492.js.map} +1 -1
- package/dist/chunk-ykbehyp9.js +17 -0
- package/dist/{chunk-c37g1gzy.js.map → chunk-ykbehyp9.js.map} +4 -3
- package/dist/{chunk-0n8t329w.js → chunk-z16nyxb8.js} +2 -2
- package/dist/{chunk-0n8t329w.js.map → chunk-z16nyxb8.js.map} +1 -1
- package/dist/{chunk-fx02sqe2.js → chunk-z9ydpvc8.js} +3 -3
- package/dist/{chunk-fx02sqe2.js.map → chunk-z9ydpvc8.js.map} +1 -1
- package/dist/chunk-zyw42zny.js +217 -0
- package/dist/chunk-zyw42zny.js.map +16 -0
- package/dist/config/index.js +1 -1
- package/dist/console/run.js +2 -2
- package/dist/console/run.js.map +1 -1
- package/dist/container/index.js +2 -2
- package/dist/container/index.js.map +1 -1
- package/dist/database/index.js +2 -2
- package/dist/database/index.js.map +1 -1
- package/dist/email/index.js +2 -2
- package/dist/email/index.js.map +2 -2
- package/dist/facades/Lock.d.ts +24 -0
- package/dist/facades/Lock.d.ts.map +1 -0
- package/dist/facades/index.d.ts +1 -0
- package/dist/facades/index.d.ts.map +1 -1
- package/dist/facades/index.js +2 -2
- package/dist/facades/index.js.map +1 -1
- package/dist/foundation/index.js +2 -2
- package/dist/foundation/index.js.map +1 -1
- package/dist/http/index.js +2 -2
- package/dist/http/index.js.map +1 -1
- package/dist/i18n/dictionaryRuntime.js +2 -2
- package/dist/i18n/dictionaryRuntime.js.map +1 -1
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +1 -1
- package/dist/kernel/index.js +2 -2
- package/dist/kernel/index.js.map +2 -2
- package/dist/orm/index.js +2 -2
- package/dist/orm/index.js.map +2 -2
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/services/cron/CronJob.d.ts +37 -1
- package/dist/services/cron/CronJob.d.ts.map +1 -1
- package/dist/services/cron/ScheduleServiceProvider.d.ts.map +1 -1
- package/dist/services/cron/Scheduler.d.ts +19 -1
- package/dist/services/cron/Scheduler.d.ts.map +1 -1
- package/dist/services/index.d.ts +5 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +3 -3
- package/dist/services/index.js.map +2 -2
- package/dist/services/lock/DatabaseLockStore.d.ts +84 -0
- package/dist/services/lock/DatabaseLockStore.d.ts.map +1 -0
- package/dist/services/lock/LockManager.d.ts +93 -0
- package/dist/services/lock/LockManager.d.ts.map +1 -0
- package/dist/services/lock/LockStore.d.ts +87 -0
- package/dist/services/lock/LockStore.d.ts.map +1 -0
- package/dist/services/lock/MemoryLockStore.d.ts +28 -0
- package/dist/services/lock/MemoryLockStore.d.ts.map +1 -0
- package/dist/services/lock/lockStoreContract.d.ts +13 -0
- package/dist/services/lock/lockStoreContract.d.ts.map +1 -0
- package/dist/services/queue/DatabaseQueueDriver.d.ts +7 -0
- package/dist/services/queue/DatabaseQueueDriver.d.ts.map +1 -1
- package/dist/services/queue/Job.d.ts +66 -0
- package/dist/services/queue/Job.d.ts.map +1 -1
- package/dist/services/queue/QueueDriver.d.ts +9 -0
- package/dist/services/queue/QueueDriver.d.ts.map +1 -1
- package/dist/services/queue/QueueManager.d.ts +46 -0
- package/dist/services/queue/QueueManager.d.ts.map +1 -1
- package/dist/services/queue/QueueServiceProvider.d.ts.map +1 -1
- package/dist/services/queue/config.d.ts +13 -0
- package/dist/services/queue/config.d.ts.map +1 -1
- package/dist/services/queue/work.js +2 -2
- package/dist/services/queue/work.js.map +2 -2
- package/dist/support/index.js +2 -2
- package/dist/support/index.js.map +2 -2
- package/package.json +1 -1
- package/dist/chunk-4bh0maq0.js +0 -5
- package/dist/chunk-c37g1gzy.js +0 -17
- package/dist/chunk-cyze295m.js +0 -5
- package/dist/chunk-g8tgp3ja.js +0 -19
- package/dist/chunk-rgcfqq21.js +0 -5
- package/dist/chunk-rgcfqq21.js.map +0 -10
- package/dist/chunk-svzdv2rf.js +0 -5
- package/dist/chunk-t4x7q9x8.js +0 -142
- package/dist/chunk-t4x7q9x8.js.map +0 -13
- /package/dist/{chunk-dve6ryfd.js.map → chunk-2yyr5tdc.js.map} +0 -0
- /package/dist/{chunk-aq1hjk00.js.map → chunk-3fjkbcra.js.map} +0 -0
- /package/dist/{chunk-7jshf4ms.js.map → chunk-jrp35qrk.js.map} +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { type LockStore } from "./LockStore";
|
|
2
|
+
export type AcquireOptions = {
|
|
3
|
+
/** The lease, in milliseconds. Default one minute. */
|
|
4
|
+
ttl?: number;
|
|
5
|
+
/**
|
|
6
|
+
* How long to keep trying when the lock is held, in milliseconds. Default
|
|
7
|
+
* `0`: one try.
|
|
8
|
+
*/
|
|
9
|
+
wait?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Renew the lease every third of `ttl` until the lock is released. Default
|
|
12
|
+
* `true` for `run`, `false` for `acquire`, whose caller may never release.
|
|
13
|
+
*/
|
|
14
|
+
renew?: boolean;
|
|
15
|
+
};
|
|
16
|
+
export type LockRunResult<T> = {
|
|
17
|
+
acquired: true;
|
|
18
|
+
value: T;
|
|
19
|
+
} | {
|
|
20
|
+
acquired: false;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* One hold on a lock, from a successful `acquire` until `release` or the end
|
|
24
|
+
* of its lease.
|
|
25
|
+
*
|
|
26
|
+
* `token` is the fencing token: it grows with each new holder of the name, so
|
|
27
|
+
* a write that records it can be refused when an older holder tries to make
|
|
28
|
+
* it late. `fence` does that refusal for writes to the application's own
|
|
29
|
+
* database.
|
|
30
|
+
*
|
|
31
|
+
* `lost` aborts when the hold is known to be gone: a renewal found another
|
|
32
|
+
* holder, or the lease ran out by this process's clock without a successful
|
|
33
|
+
* renewal. The local deadline is measured from just before each request that
|
|
34
|
+
* set the lease, so it always falls before the store's own expiry.
|
|
35
|
+
*/
|
|
36
|
+
export declare class HeldLock {
|
|
37
|
+
private readonly store;
|
|
38
|
+
readonly name: string;
|
|
39
|
+
readonly owner: string;
|
|
40
|
+
readonly token: number;
|
|
41
|
+
readonly ttl: number;
|
|
42
|
+
readonly lost: AbortSignal;
|
|
43
|
+
private readonly controller;
|
|
44
|
+
private deadline;
|
|
45
|
+
private expiryTimer;
|
|
46
|
+
private renewTimer;
|
|
47
|
+
private done;
|
|
48
|
+
constructor(store: LockStore, name: string, owner: string, token: number, ttl: number, requestedAt: number);
|
|
49
|
+
/** Whether the lease has run out by this process's clock, or the hold was lost. */
|
|
50
|
+
get expired(): boolean;
|
|
51
|
+
/** Renews the lease. `false`, and `lost` aborted, when the hold was already gone. */
|
|
52
|
+
extend(ttl?: number): Promise<boolean>;
|
|
53
|
+
/** Asks the store whether this hold is still current. */
|
|
54
|
+
isHeld(): Promise<boolean>;
|
|
55
|
+
/**
|
|
56
|
+
* Runs `fn` only while this hold is current, and keeps the lock from
|
|
57
|
+
* changing hands until it settles; rejects with `LockLostError` otherwise.
|
|
58
|
+
* On the database store `fn` runs in a transaction on the store's
|
|
59
|
+
* connection, so ORM writes inside it commit only if the hold was current.
|
|
60
|
+
*/
|
|
61
|
+
fence<T>(fn: () => Promise<T>): Promise<T>;
|
|
62
|
+
/** Ends the hold. `false` when it had already been lost. */
|
|
63
|
+
release(): Promise<boolean>;
|
|
64
|
+
/** Renews every third of the lease until `release`. */
|
|
65
|
+
startRenewing(): void;
|
|
66
|
+
/** @internal Marks the hold as gone and stops every timer. */
|
|
67
|
+
markLost(detail?: string): void;
|
|
68
|
+
private stop;
|
|
69
|
+
private armExpiry;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Named locks with leases and fencing tokens, over a `LockStore`. The queue
|
|
73
|
+
* builds one over its own storage (`app(QueueManager).locks`), so with the
|
|
74
|
+
* database driver the locks hold across every process sharing the database.
|
|
75
|
+
* The `Lock` facade fronts it.
|
|
76
|
+
*/
|
|
77
|
+
export declare class LockManager {
|
|
78
|
+
readonly store: LockStore;
|
|
79
|
+
static token: string;
|
|
80
|
+
constructor(store: LockStore);
|
|
81
|
+
/** Takes the lock, or resolves `null` if it is held (after `wait`, when given). */
|
|
82
|
+
acquire(name: string, options?: AcquireOptions): Promise<HeldLock | null>;
|
|
83
|
+
/**
|
|
84
|
+
* Runs `fn` while holding the lock, renewing the lease as it runs, and
|
|
85
|
+
* releases it after. `{ acquired: false }` when the lock was held.
|
|
86
|
+
*
|
|
87
|
+
* If the hold is lost while `fn` runs, `lock.lost` aborts, and once `fn`
|
|
88
|
+
* settles this rejects with `LockLostError` instead of resolving: the caller
|
|
89
|
+
* must not treat work done without the lock as done under it.
|
|
90
|
+
*/
|
|
91
|
+
run<T>(name: string, options: AcquireOptions, fn: (lock: HeldLock) => Promise<T> | T): Promise<LockRunResult<T>>;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=LockManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LockManager.d.ts","sourceRoot":"","sources":["../../../services/lock/LockManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE5D,MAAM,MAAM,cAAc,GAAG;IAC3B,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,KAAK,CAAA;CAAE,CAAC;AAOlF;;;;;;;;;;;;;GAaG;AACH,qBAAa,QAAQ;IASjB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM;IAZtB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAA4C;IAC/D,OAAO,CAAC,UAAU,CAA6C;IAC/D,OAAO,CAAC,IAAI,CAAS;gBAGF,KAAK,EAAE,SAAS,EACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM;IAOrB,mFAAmF;IACnF,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,qFAAqF;IAC/E,MAAM,CAAC,GAAG,SAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAc9C,yDAAyD;IACnD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAOhC;;;;;OAKG;IACG,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAUhD,4DAA4D;IACtD,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAMjC,uDAAuD;IACvD,aAAa;IAeb,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;IAOxB,OAAO,CAAC,IAAI;IAQZ,OAAO,CAAC,SAAS;CAQlB;AAED;;;;;GAKG;AACH,qBAAa,WAAW;IAGV,QAAQ,CAAC,KAAK,EAAE,SAAS;IAFrC,MAAM,CAAC,KAAK,SAAW;gBAEF,KAAK,EAAE,SAAS;IAErC,mFAAmF;IAC7E,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAoBnF;;;;;;;OAOG;IACG,GAAG,CAAC,CAAC,EACT,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,EACvB,EAAE,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GACrC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;CAkB7B"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where locks are kept: one record per lock name, with the current holder, a
|
|
3
|
+
* fencing token and a lease.
|
|
4
|
+
*
|
|
5
|
+
* ### The model
|
|
6
|
+
*
|
|
7
|
+
* A lock is held by an **owner** (a random id per acquisition, or a job's id)
|
|
8
|
+
* until its **lease** runs out or the owner releases it. Every successful
|
|
9
|
+
* `acquire` raises the name's **token** by one, so tokens only grow per name and
|
|
10
|
+
* a newer holder always has a larger one than any older holder. A store never
|
|
11
|
+
* forgets a name on release, which is what keeps the token growing; `prune`
|
|
12
|
+
* (on a store that has it) removes names idle for long enough.
|
|
13
|
+
*
|
|
14
|
+
* A lease that runs out is lost, even if nobody has taken the lock since:
|
|
15
|
+
* `extend`, `held` and `fence` all refuse it. That is the rule that makes the
|
|
16
|
+
* token mean something. A holder whose process stalled past its lease cannot
|
|
17
|
+
* renew its way back in after another process may have started the same work.
|
|
18
|
+
*
|
|
19
|
+
* ### Time
|
|
20
|
+
*
|
|
21
|
+
* Durations cross this interface as relative milliseconds, as they do for
|
|
22
|
+
* `QueueDriver`, so a store shared between machines can measure every lease on
|
|
23
|
+
* one clock, its own.
|
|
24
|
+
*/
|
|
25
|
+
export interface LockStore {
|
|
26
|
+
/**
|
|
27
|
+
* Takes `name` for `owner` for `ttlMs`, if nobody holds it or the holder's
|
|
28
|
+
* lease ran out, and resolves to the new fencing token. `null` when it is
|
|
29
|
+
* held. Two concurrent calls, from any processes sharing the store, never
|
|
30
|
+
* both succeed.
|
|
31
|
+
*/
|
|
32
|
+
acquire(name: string, owner: string, ttlMs: number): Promise<number | null>;
|
|
33
|
+
/**
|
|
34
|
+
* Renews a lease to `ttlMs` from now, and resolves to whether `owner` still
|
|
35
|
+
* held it with `token`. A lease that already ran out is not renewed.
|
|
36
|
+
*/
|
|
37
|
+
extend(name: string, owner: string, token: number, ttlMs: number): Promise<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Ends a hold, and resolves to whether `owner` held it (with `token`, when
|
|
40
|
+
* given) and its lease had not run out. Releasing a lock someone else now
|
|
41
|
+
* holds does nothing.
|
|
42
|
+
*/
|
|
43
|
+
release(name: string, owner: string, token?: number): Promise<boolean>;
|
|
44
|
+
/** The current holder, or `null` when the lock is free or its lease ran out. */
|
|
45
|
+
holder(name: string): Promise<{
|
|
46
|
+
owner: string;
|
|
47
|
+
token: number;
|
|
48
|
+
} | null>;
|
|
49
|
+
/** Whether `owner` still holds `name` with `token`, its lease running. */
|
|
50
|
+
held(name: string, owner: string, token: number): Promise<boolean>;
|
|
51
|
+
/**
|
|
52
|
+
* Raises a counter kept under `name` to `value` if it is below it, and
|
|
53
|
+
* resolves to whether it did. For "once per tick across instances": every
|
|
54
|
+
* instance advances to the tick's number and only the first one gets `true`.
|
|
55
|
+
* A name used here must not also be used with `acquire`.
|
|
56
|
+
*/
|
|
57
|
+
advance(name: string, value: number): Promise<boolean>;
|
|
58
|
+
/**
|
|
59
|
+
* Runs `fn` only if `owner` still holds `name` with `token`, and keeps the
|
|
60
|
+
* lock from changing hands until `fn` settles. Rejects with `LockLostError`
|
|
61
|
+
* when the hold is gone. On the database store this is a transaction that
|
|
62
|
+
* locks the lock's row first, so writes `fn` makes through the ORM on the
|
|
63
|
+
* same connection commit only while the hold is current, and a new holder's
|
|
64
|
+
* `acquire` waits for that commit.
|
|
65
|
+
*/
|
|
66
|
+
fence<T>(name: string, owner: string, token: number, fn: () => Promise<T>): Promise<T>;
|
|
67
|
+
/**
|
|
68
|
+
* Counts one hit against a fixed window kept under `name`: allowed when
|
|
69
|
+
* fewer than `limit` were counted in the current window, which starts at the
|
|
70
|
+
* first hit after the last one ended and lasts `windowMs`. A refused hit is
|
|
71
|
+
* not counted. `resetInMs` is how long until the window ends. A name used
|
|
72
|
+
* here must not also be used with `acquire` or `advance`.
|
|
73
|
+
*/
|
|
74
|
+
hit(name: string, limit: number, windowMs: number): Promise<{
|
|
75
|
+
allowed: boolean;
|
|
76
|
+
resetInMs: number;
|
|
77
|
+
}>;
|
|
78
|
+
/** Takes back one counted hit from the current window, if it has one. */
|
|
79
|
+
refund(name: string): Promise<void>;
|
|
80
|
+
}
|
|
81
|
+
/** The hold on a lock ended before the work it guarded did. */
|
|
82
|
+
export declare class LockLostError extends Error {
|
|
83
|
+
readonly lock: string;
|
|
84
|
+
readonly token: number;
|
|
85
|
+
constructor(lock: string, token: number, detail?: string);
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=LockStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LockStore.d.ts","sourceRoot":"","sources":["../../../services/lock/LockStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE5E;;;OAGG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpF;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEvE,gFAAgF;IAChF,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAEvE,0EAA0E;IAC1E,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEnE;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEvD;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAEvF;;;;;;OAMG;IACH,GAAG,CACD,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAEpD,yEAAyE;IACzE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,+DAA+D;AAC/D,qBAAa,aAAc,SAAQ,KAAK;IAEpC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM;gBADb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACtB,MAAM,SAAgD;CAKzD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type LockStore } from "./LockStore";
|
|
2
|
+
/**
|
|
3
|
+
* Locks in this process's memory. Correct for one process and useless across
|
|
4
|
+
* several: two servers each have their own map, so each takes every lock. It
|
|
5
|
+
* is what the queue uses with the memory driver, and in tests.
|
|
6
|
+
*/
|
|
7
|
+
export declare class MemoryLockStore implements LockStore {
|
|
8
|
+
private readonly entries;
|
|
9
|
+
private readonly counters;
|
|
10
|
+
acquire(name: string, owner: string, ttlMs: number): Promise<number | null>;
|
|
11
|
+
extend(name: string, owner: string, token: number, ttlMs: number): Promise<boolean>;
|
|
12
|
+
release(name: string, owner: string, token?: number): Promise<boolean>;
|
|
13
|
+
holder(name: string): Promise<{
|
|
14
|
+
owner: string;
|
|
15
|
+
token: number;
|
|
16
|
+
}>;
|
|
17
|
+
held(name: string, owner: string, token: number): Promise<boolean>;
|
|
18
|
+
advance(name: string, value: number): Promise<boolean>;
|
|
19
|
+
fence<T>(name: string, owner: string, token: number, fn: () => Promise<T>): Promise<T>;
|
|
20
|
+
private readonly windows;
|
|
21
|
+
hit(name: string, limit: number, windowMs: number): Promise<{
|
|
22
|
+
allowed: boolean;
|
|
23
|
+
resetInMs: number;
|
|
24
|
+
}>;
|
|
25
|
+
refund(name: string): Promise<void>;
|
|
26
|
+
private current;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=MemoryLockStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemoryLockStore.d.ts","sourceRoot":"","sources":["../../../services/lock/MemoryLockStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAU5D;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,SAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IAEhD,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAS3E,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOnF,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQtE,MAAM,CAAC,IAAI,EAAE,MAAM;;;;IAMnB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMtD,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAW5F,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwD;IAE1E,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;IAYjD,MAAM,CAAC,IAAI,EAAE,MAAM;IAKzB,OAAO,CAAC,OAAO;CAMhB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type LockStore } from "./LockStore";
|
|
2
|
+
/**
|
|
3
|
+
* What every `LockStore` promises, run by each store's test file against
|
|
4
|
+
* itself. `open` returns a fresh, empty storage; `store()` hands out a store
|
|
5
|
+
* over it, and for a database a new client each time, so "two processes" is
|
|
6
|
+
* two clients on one database. Not a `*.test.ts` file, so vitest only runs it
|
|
7
|
+
* through those files.
|
|
8
|
+
*/
|
|
9
|
+
export declare function lockStoreContract(name: string, open: () => Promise<{
|
|
10
|
+
store(): LockStore;
|
|
11
|
+
dispose(): Promise<void>;
|
|
12
|
+
}>): void;
|
|
13
|
+
//# sourceMappingURL=lockStoreContract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lockStoreContract.d.ts","sourceRoot":"","sources":["../../../services/lock/lockStoreContract.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE5D;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,OAAO,CAAC;IAAE,KAAK,IAAI,SAAS,CAAC;IAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,QA8JtE"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DatabaseConnection } from "../../database/Connection";
|
|
2
2
|
import type { Dialect } from "../../database/dialect";
|
|
3
|
+
import { DatabaseLockStore } from "../lock/DatabaseLockStore";
|
|
3
4
|
import type { ClaimOptions, ClaimedJob, EnqueueJob, JobFailure, JobRelease, QueueDriver } from "./QueueDriver";
|
|
4
5
|
export type DatabaseQueueDriverOptions = {
|
|
5
6
|
/**
|
|
@@ -127,6 +128,12 @@ export declare class DatabaseQueueDriver implements QueueDriver {
|
|
|
127
128
|
createTable(): Promise<void>;
|
|
128
129
|
enqueue(job: EnqueueJob): Promise<string>;
|
|
129
130
|
private insert;
|
|
131
|
+
/**
|
|
132
|
+
* Locks in the `gemi_locks` table of the same connection, so unique jobs,
|
|
133
|
+
* `withoutOverlapping` and `onOneServer` hold across every process sharing
|
|
134
|
+
* this database. The table is only touched when one of those is used.
|
|
135
|
+
*/
|
|
136
|
+
lockStore(): DatabaseLockStore;
|
|
130
137
|
joinsTransaction(): boolean;
|
|
131
138
|
/**
|
|
132
139
|
* The open ORM transaction, when an `enqueue` should be written on it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatabaseQueueDriver.d.ts","sourceRoot":"","sources":["../../../services/queue/DatabaseQueueDriver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"DatabaseQueueDriver.d.ts","sourceRoot":"","sources":["../../../services/queue/DatabaseQueueDriver.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,61 @@ export declare class Job {
|
|
|
9
9
|
* free.
|
|
10
10
|
*/
|
|
11
11
|
backoff: number | number[];
|
|
12
|
+
/**
|
|
13
|
+
* Makes the job unique per key, across every process sharing the queue's
|
|
14
|
+
* storage. Return a key from the dispatch arguments, or `undefined` for a
|
|
15
|
+
* dispatch that should not be unique. While a job with the same key is
|
|
16
|
+
* waiting or running, another dispatch is not queued: it resolves to the
|
|
17
|
+
* id of the job already there. The key is freed when that job completes or
|
|
18
|
+
* is dead-lettered, and at the latest after `uniqueFor`.
|
|
19
|
+
*
|
|
20
|
+
* The default returns `undefined`: a job is not unique unless it says so.
|
|
21
|
+
*/
|
|
22
|
+
uniqueId(..._args: any[]): string | number | undefined | null;
|
|
23
|
+
/**
|
|
24
|
+
* How long a unique job's key is held at most, in milliseconds, so a job
|
|
25
|
+
* lost with its process does not block its key forever. Default one hour.
|
|
26
|
+
*/
|
|
27
|
+
uniqueFor: number;
|
|
28
|
+
/**
|
|
29
|
+
* Rate limits per key, computed from the dispatch arguments: at most
|
|
30
|
+
* `limit` jobs admitted per fixed `window` (milliseconds) under each `key`,
|
|
31
|
+
* across every process sharing the queue's storage. A job over a limit is
|
|
32
|
+
* put back until the window resets, without spending an attempt. Counted
|
|
33
|
+
* when the job is admitted to run, whether it then succeeds or not.
|
|
34
|
+
*/
|
|
35
|
+
throttle(..._args: any[]): JobThrottle | JobThrottle[] | undefined | null;
|
|
36
|
+
/**
|
|
37
|
+
* At most `limit` jobs with this `key` running at once, across every process
|
|
38
|
+
* sharing the queue's storage. A job with no free slot waits, without
|
|
39
|
+
* spending an attempt.
|
|
40
|
+
*/
|
|
41
|
+
concurrency(..._args: any[]): JobConcurrency | undefined | null;
|
|
42
|
+
/**
|
|
43
|
+
* Called from `run`: puts the job back to wait `delayMs` once `run`
|
|
44
|
+
* returns, without counting the attempt or calling any hook. For a provider
|
|
45
|
+
* that answered "slow down". Not available to `worker` jobs.
|
|
46
|
+
*/
|
|
47
|
+
release(delayMs?: number): void;
|
|
48
|
+
/**
|
|
49
|
+
* Called from `run`: fails this attempt once `run` returns, as a throw
|
|
50
|
+
* would. With `retry: false` it is dead-lettered at once, whatever
|
|
51
|
+
* `maxAttempts` says: for work that must not be repeated, such as a send
|
|
52
|
+
* whose acceptance is uncertain. A throw after `fail(..., { retry: false })`
|
|
53
|
+
* is dead-lettered too. Not available to `worker` jobs.
|
|
54
|
+
*/
|
|
55
|
+
fail(error: unknown, options?: {
|
|
56
|
+
retry?: boolean;
|
|
57
|
+
}): void;
|
|
58
|
+
/** @internal What `release` or `fail` asked for during this run. */
|
|
59
|
+
$outcome: {
|
|
60
|
+
kind: "release";
|
|
61
|
+
delayMs: number;
|
|
62
|
+
} | {
|
|
63
|
+
kind: "fail";
|
|
64
|
+
error: Error;
|
|
65
|
+
retry: boolean;
|
|
66
|
+
} | undefined;
|
|
12
67
|
run(..._args: any[]): Promise<any> | any;
|
|
13
68
|
onFail(_error: Error, ..._args: any[]): void;
|
|
14
69
|
onSuccess(_result: any, ..._args: any[]): void;
|
|
@@ -24,4 +79,15 @@ export declare class Job {
|
|
|
24
79
|
*/
|
|
25
80
|
static dispatch<T extends Job>(this: new () => T, ...args: Parameters<T["run"]>): Promise<string>;
|
|
26
81
|
}
|
|
82
|
+
export type JobThrottle = {
|
|
83
|
+
/** Shared by every job that counts against the same budget. */
|
|
84
|
+
key: string;
|
|
85
|
+
limit: number;
|
|
86
|
+
/** The window, in milliseconds. */
|
|
87
|
+
window: number;
|
|
88
|
+
};
|
|
89
|
+
export type JobConcurrency = {
|
|
90
|
+
key: string;
|
|
91
|
+
limit: number;
|
|
92
|
+
};
|
|
27
93
|
//# sourceMappingURL=Job.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Job.d.ts","sourceRoot":"","sources":["../../../services/queue/Job.ts"],"names":[],"mappings":"AAGA,qBAAa,GAAG;IACd,MAAM,CAAC,IAAI,SAAW;IACtB,MAAM,UAAS;IACf,WAAW,SAAK;IAEhB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAK;IAE/B,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG;IAExC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI;IAC5C,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI;IAC9C,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI;IAElD;;;;;;;;OAQG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,GAAG,EAC3B,IAAI,EAAE,UAAU,CAAC,EACjB,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC;CAOnB"}
|
|
1
|
+
{"version":3,"file":"Job.d.ts","sourceRoot":"","sources":["../../../services/queue/Job.ts"],"names":[],"mappings":"AAGA,qBAAa,GAAG;IACd,MAAM,CAAC,IAAI,SAAW;IACtB,MAAM,UAAS;IACf,WAAW,SAAK;IAEhB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAK;IAE/B;;;;;;;;;OASG;IACH,QAAQ,CAAC,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI;IAI7D;;;OAGG;IACH,SAAS,SAAe;IAExB;;;;;;OAMG;IACH,QAAQ,CAAC,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,WAAW,GAAG,WAAW,EAAE,GAAG,SAAS,GAAG,IAAI;IAIzE;;;;OAIG;IACH,WAAW,CAAC,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,cAAc,GAAG,SAAS,GAAG,IAAI;IAI/D;;;;OAIG;IACH,OAAO,CAAC,OAAO,SAAI,GAAG,IAAI;IAI1B;;;;;;OAMG;IACH,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,IAAI;IAQ7D,oEAAoE;IACpE,QAAQ,EACJ;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GACpC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAC9C,SAAS,CAAC;IAEd,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG;IAExC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI;IAC5C,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI;IAC9C,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI;IAElD;;;;;;;;OAQG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,GAAG,EAC3B,IAAI,EAAE,UAAU,CAAC,EACjB,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC;CAOnB;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC"}
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
* computed on the dispatching machine would carry that machine's skew into
|
|
41
41
|
* every other one.
|
|
42
42
|
*/
|
|
43
|
+
import type { LockStore } from "../lock/LockStore";
|
|
43
44
|
export interface QueueDriver {
|
|
44
45
|
/**
|
|
45
46
|
* Records a job and returns its id. The job is claimable once `delayMs` has
|
|
@@ -127,6 +128,14 @@ export interface QueueDriver {
|
|
|
127
128
|
* that cannot guarantee it should leave this out and be polled.
|
|
128
129
|
*/
|
|
129
130
|
subscribe?(wake: () => void): () => void;
|
|
131
|
+
/**
|
|
132
|
+
* A `LockStore` over the same storage, for the locks the queue and the
|
|
133
|
+
* scheduler take: unique jobs, `withoutOverlapping` and `onOneServer`, and
|
|
134
|
+
* the `Lock` facade. Optional: without it the locks are kept in this
|
|
135
|
+
* process's memory, which only serializes work within one process. Called
|
|
136
|
+
* once per manager.
|
|
137
|
+
*/
|
|
138
|
+
lockStore?(): LockStore;
|
|
130
139
|
}
|
|
131
140
|
export type EnqueueJob = {
|
|
132
141
|
/** The job's registered name — its class's `static name`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueueDriver.d.ts","sourceRoot":"","sources":["../../../services/queue/QueueDriver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,OAAO,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE1C;;;;;;;;;;;;;;;;;;OAkBG;IACH,gBAAgB,CAAC,IAAI,OAAO,CAAC;IAE7B;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAEnE,iEAAiE;IACjE,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzC;;;;;OAKG;IACH,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1D;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7D;;;OAGG;IACH,SAAS,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErE;;;;;;;OAOG;IACH,SAAS,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEzC;;;;;;OAMG;IACH,SAAS,CAAC,CAAC,IAAI,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"QueueDriver.d.ts","sourceRoot":"","sources":["../../../services/queue/QueueDriver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,OAAO,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE1C;;;;;;;;;;;;;;;;;;OAkBG;IACH,gBAAgB,CAAC,IAAI,OAAO,CAAC;IAE7B;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAEnE,iEAAiE;IACjE,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzC;;;;;OAKG;IACH,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1D;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7D;;;OAGG;IACH,SAAS,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErE;;;;;;;OAOG;IACH,SAAS,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEzC;;;;;;OAMG;IACH,SAAS,CAAC,CAAC,IAAI,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAEzC;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,SAAS,CAAC;CACzB;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5D,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Application } from "../../foundation/Application";
|
|
2
|
+
import { LockManager } from "../lock/LockManager";
|
|
2
3
|
import { Job } from "./Job";
|
|
3
4
|
import { type QueueConfig } from "./config";
|
|
4
5
|
import type { ClaimedJob, QueueDriver } from "./QueueDriver";
|
|
@@ -57,6 +58,7 @@ export declare class QueueManager {
|
|
|
57
58
|
private heartbeatTimer;
|
|
58
59
|
/** Unknown names already reported as left for another replica; see `run`. */
|
|
59
60
|
private readonly releasedNames;
|
|
61
|
+
private lockManager;
|
|
60
62
|
/**
|
|
61
63
|
* `application` is entered around every job, so `app()` inside one resolves
|
|
62
64
|
* to it rather than to whichever application happens to be the static
|
|
@@ -161,6 +163,38 @@ export declare class QueueManager {
|
|
|
161
163
|
*/
|
|
162
164
|
reportFailure?: boolean;
|
|
163
165
|
}): Promise<string>;
|
|
166
|
+
/**
|
|
167
|
+
* The locks unique jobs, cron jobs' `withoutOverlapping` and `onOneServer`,
|
|
168
|
+
* and the `Lock` facade use, over the store the `locks` setting names. Built
|
|
169
|
+
* on first use, so an app that uses none of them never touches the store.
|
|
170
|
+
*/
|
|
171
|
+
get locks(): LockManager;
|
|
172
|
+
private resolveLockStore;
|
|
173
|
+
/**
|
|
174
|
+
* The lock key a dispatch of a unique job takes, or `undefined` for a job
|
|
175
|
+
* that does not declare `uniqueId` or a dispatch it returned nothing for.
|
|
176
|
+
*/
|
|
177
|
+
private uniqueKey;
|
|
178
|
+
/**
|
|
179
|
+
* Records a unique job if its key is free, and otherwise resolves to the id
|
|
180
|
+
* of the job holding it. The key's lock is owned by the job's id, which is
|
|
181
|
+
* how the job frees it when it ends and how a duplicate finds it.
|
|
182
|
+
*
|
|
183
|
+
* Inside a transaction the whole dispatch waits for the commit, even on a
|
|
184
|
+
* driver that could join the transaction. The key is taken outside it, so
|
|
185
|
+
* written on the transaction the job could roll back and leave its key held
|
|
186
|
+
* for `uniqueFor` with nothing queued under it. A held dispatch resolves to
|
|
187
|
+
* the id the job will have, and is dropped at the commit if a job with the
|
|
188
|
+
* same key is queued by then.
|
|
189
|
+
*/
|
|
190
|
+
private pushUnique;
|
|
191
|
+
private recordUnique;
|
|
192
|
+
/**
|
|
193
|
+
* Frees a unique job's key once the job has ended for good: completed or
|
|
194
|
+
* dead-lettered. Released by the job's id, so a key a newer dispatch holds
|
|
195
|
+
* after `uniqueFor` ran out is left alone.
|
|
196
|
+
*/
|
|
197
|
+
private releaseUnique;
|
|
164
198
|
/** `push`, once it is known that the job is recorded now. */
|
|
165
199
|
private record;
|
|
166
200
|
/**
|
|
@@ -275,6 +309,18 @@ export declare class QueueManager {
|
|
|
275
309
|
* escape the queue with the job's slot still counted as taken.
|
|
276
310
|
*/
|
|
277
311
|
private run;
|
|
312
|
+
/**
|
|
313
|
+
* Takes a slot under the job's `concurrency` key and a hit under each of
|
|
314
|
+
* its `throttle` keys, all in the queue's lock store, so the limits hold
|
|
315
|
+
* across every process sharing it. Resolves to what to undo after the run,
|
|
316
|
+
* or `undefined` when the job was released to wait for capacity.
|
|
317
|
+
*
|
|
318
|
+
* Concurrency is `limit` slot locks per key, each leased for the
|
|
319
|
+
* visibility timeout and renewed while the job runs, so a slot held by a
|
|
320
|
+
* dead process frees itself like the job's own lease. Throttles are fixed
|
|
321
|
+
* windows counted when a job is admitted, whether it then succeeds or not.
|
|
322
|
+
*/
|
|
323
|
+
private admit;
|
|
278
324
|
}
|
|
279
325
|
/**
|
|
280
326
|
* Whether this process should claim from a driver shared with other
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueueManager.d.ts","sourceRoot":"","sources":["../../../services/queue/QueueManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAMhE,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAEjE,OAAO,KAAK,EAAgB,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAmG3E,OAAO,CAAC,MAAM,CAAC;IACb;;;;;;;;;;OAUG;IACH,IAAI,cAAc,EAAE;QAAE,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,GAAG,SAAS,CAAC;CAC9D;AAED,uCAAuC;AACvC,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;;OAMG;IACH,UAAU,EAAE,UAAU,EAAE,CAAC;CAC1B,CAAC;AAEF,qBAAa,YAAY;IACvB,MAAM,CAAC,KAAK,SAAW;IAEvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,CAAC,CAAM;IAEzC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAE7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IACtD;;;;;;;;;OASG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAGrB;IACJ,OAAO,CAAC,KAAK,CAA0C;IACvD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,KAAK,CAAS;IACtB,oFAAoF;IACpF,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,cAAc,CAA6C;IACnE,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;
|
|
1
|
+
{"version":3,"file":"QueueManager.d.ts","sourceRoot":"","sources":["../../../services/queue/QueueManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAMhE,OAAO,EAAiB,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIjE,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAEjE,OAAO,KAAK,EAAgB,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAmG3E,OAAO,CAAC,MAAM,CAAC;IACb;;;;;;;;;;OAUG;IACH,IAAI,cAAc,EAAE;QAAE,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,GAAG,SAAS,CAAC;CAC9D;AAED,uCAAuC;AACvC,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;;OAMG;IACH,UAAU,EAAE,UAAU,EAAE,CAAC;CAC1B,CAAC;AAEF,qBAAa,YAAY;IACvB,MAAM,CAAC,KAAK,SAAW;IAEvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,CAAC,CAAM;IAEzC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAE7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IACtD;;;;;;;;;OASG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAGrB;IACJ,OAAO,CAAC,KAAK,CAA0C;IACvD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,KAAK,CAAS;IACtB,oFAAoF;IACpF,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,cAAc,CAA6C;IACnE,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,WAAW,CAA0B;IAE7C;;;;;OAKG;gBAED,MAAM,GAAE,WAAgB,EACxB,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,WAAW,CAAA;KAAO;IAQ7C;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,UAAU,GAAG,CAAC;IAyBlC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,WAAW,CAAC,GAAG,EAAE,UAAU,GAAG;IAK9B;;;;;;OAMG;IACH,OAAO,CAAC,KAAK;IAab;;;;;;;;;;;;OAYG;IACH,IAAI,cAAc,IAAI,aAAa,CAAC,UAAU,GAAG,CAAC,CAEjD;IAED,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAOzC;;;;;;;;;;;;;;;;OAgBG;IACH,IAAI,CACF,GAAG,EAAE,UAAU,GAAG,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;QACP;;;;;;;;WAQG;QACH,aAAa,CAAC,EAAE,OAAO,CAAC;KACpB,GACL,OAAO,CAAC,MAAM,CAAC;IAwClB;;;;OAIG;IACH,IAAI,KAAK,IAAI,WAAW,CAGvB;IAED,OAAO,CAAC,gBAAgB;IAoCxB;;;OAGG;IACH,OAAO,CAAC,SAAS;IAQjB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,YAAY;IA2CpB;;;;OAIG;YACW,aAAa;IAe3B,6DAA6D;IAC7D,OAAO,CAAC,MAAM;IAkEd;;;;;;;;;;;;;;;;OAgBG;IACG,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAY7C;;;OAGG;IACH,OAAO,CAAC,WAAW;IAMnB;;;OAGG;IACH,OAAO,CAAC,SAAS;IAKjB;;;;;OAKG;IACH,KAAK;IAgBL;;;;;;;;;;;;OAYG;IACG,KAAK,CAAC,SAAS,SAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IA0BvD,6EAA6E;IAC7E,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC;IAI5B,uDAAuD;IACvD,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;;;;;;;;;OAUG;YACW,IAAI;YASJ,iBAAiB;IAmD/B;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,KAAK;IAoBb,0EAA0E;IAC1E,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,IAAI;IAOZ;;;OAGG;IACH,IAAI,OAAO,YAEV;IAED,qEAAqE;IACrE,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,OAAO;IAwBf;;;;OAIG;IACH,OAAO,CAAC,SAAS;IAoBjB;;;;;;;OAOG;YACW,GAAG;IAgMjB;;;;;;;;;;OAUG;YACW,KAAK;CAiDpB;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,YAIlC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,WAEtF;AAQD,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,MAAM,UAAO,QAE5C;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,UAKrE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueueServiceProvider.d.ts","sourceRoot":"","sources":["../../../services/queue/QueueServiceProvider.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"QueueServiceProvider.d.ts","sourceRoot":"","sources":["../../../services/queue/QueueServiceProvider.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAyBhE,qBAAa,oBAAqB,SAAQ,eAAe;IACvD,QAAQ;IAYR;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACG,IAAI;IAQV;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACG,QAAQ,CAAC,OAAO,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE;;;CAqB/C;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,WAAW,QAO9D"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Application } from "../../foundation/Application";
|
|
2
2
|
import type { Job } from "./Job";
|
|
3
|
+
import type { LockStore } from "../lock/LockStore";
|
|
3
4
|
import type { QueueDriver } from "./QueueDriver";
|
|
4
5
|
export interface QueueConfig {
|
|
5
6
|
/**
|
|
@@ -105,6 +106,18 @@ export interface QueueConfig {
|
|
|
105
106
|
* unknown name there is dead-lettered at once.
|
|
106
107
|
*/
|
|
107
108
|
unknownJobGrace?: number;
|
|
109
|
+
/**
|
|
110
|
+
* Where locks are kept: the ones unique jobs, a cron job's
|
|
111
|
+
* `withoutOverlapping` and `onOneServer`, and the `Lock` facade take.
|
|
112
|
+
*
|
|
113
|
+
* `"auto"`, the default, keeps them where the driver keeps jobs: with
|
|
114
|
+
* `"database"` that is the `gemi_locks` table of the same connection, so
|
|
115
|
+
* they hold across every process sharing it; with `"memory"` it is this
|
|
116
|
+
* process. `"memory"` and `"database"` (the default connection) choose
|
|
117
|
+
* explicitly, and a `LockStore`, or a function returning one, is used as
|
|
118
|
+
* given. Nothing is read or written until one of those features is used.
|
|
119
|
+
*/
|
|
120
|
+
locks?: "auto" | "memory" | "database" | LockStore | ((application: Application) => LockStore);
|
|
108
121
|
}
|
|
109
122
|
export declare function defineQueueConfig(config: QueueConfig): QueueConfig;
|
|
110
123
|
export declare function queueConfigDefaults(): Required<QueueConfig>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../services/queue/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAGjD,MAAM,WAAW,WAAW;IAC1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC;IAE5B;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,CAAC,EACH,QAAQ,GACR,UAAU,GACV,WAAW,GACX,CAAC,CAAC,WAAW,EAAE,WAAW,KAAK,WAAW,CAAC,CAAC;IAEhD;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;;;;;;;;;;;;OAkBG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../services/queue/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAGjD,MAAM,WAAW,WAAW;IAC1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC;IAE5B;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,CAAC,EACH,QAAQ,GACR,UAAU,GACV,WAAW,GACX,CAAC,CAAC,WAAW,EAAE,WAAW,KAAK,WAAW,CAAC,CAAC;IAEhD;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;;;;;;;;;;;;OAkBG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;;;;;;;;OAUG;IACH,KAAK,CAAC,EACF,MAAM,GACN,QAAQ,GACR,UAAU,GACV,SAAS,GACT,CAAC,CAAC,WAAW,EAAE,WAAW,KAAK,SAAS,CAAC,CAAC;CAC/C;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAElE;AAED,wBAAgB,mBAAmB,IAAI,QAAQ,CAAC,WAAW,CAAC,CAW3D"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{_b as E,bc as T}from"../../chunk-zyw42zny.js";import"../../chunk-br9p390p.js";import"../../chunk-n4807648.js";import"../../chunk-ghz3e8b7.js";import"../../chunk-3fr22rtg.js";import"../../chunk-7hfv5n00.js";import"../../chunk-qxda7pzm.js";import{Lg as I,Mg as J,Pg as O}from"../../chunk-et6thczw.js";import{Tg as N}from"../../chunk-kzh8bkg5.js";import"../../chunk-j2nx0dtq.js";import L from"path";class F extends Error{name="QueueWorkerRefused"}class H{kernel;stopping;keepAlive;settings;constructor(y,z={}){this.kernel=y;this.settings={...J(),...z}}async start(){if(await this.kernel.waitForBoot(),this.stopping)return;let y=this.kernel.app;if(!y.bound(E))throw new F("[gemi] `gemi queue:work` has no queue to claim from: this application does not register QueueServiceProvider.");let z=y.make(E);if(!z.durable)throw new F('[gemi] `gemi queue:work` refuses to start: the queue uses the memory driver, which keeps each job in the process that dispatched it, so a worker never sees one. Set `driver: "database"` (or another driver every process can reach) in app/config/queue.ts, or run jobs in the server and drop the worker.');z.start(),this.keepAlive=setInterval(()=>{},1073741824),console.log(`[gemi] Queue worker started: claiming up to ${z.config.concurrency} job(s) at a time.`)}stop(y={}){return this.stopping??=this.drain({...this.settings,...y}),this.stopping}async drain(y){I();let z=this.kernel.app,A=z.resolved(E)?z.make(E):void 0;if(A)console.log(`[gemi] Shutting down: waiting for ${A.running} running job(s) (up to ${y.timeoutMs/1000}s).`),await A.drain(y.timeoutMs);let B=await this.kernel.shutdown({timeoutMs:y.providerTimeoutMs});clearInterval(this.keepAlive);let C=(A?.running??0)===0&&B.failed.length===0&&B.timedOut.length===0;return console.log(`[gemi] Shutdown ${C?"complete":"finished with errors"}.`),C?0:1}}async function U(){let y=N();process.env.ROOT_DIR=y,process.env.APP_DIR=L.join(y,"app"),T();let z=L.join(y,"app/kernel/Kernel.ts"),{default:A}=await import(z);if(typeof A!=="function")return console.error(`[gemi] ${z} has no default export to boot the worker from.`),1;let B=new A;B.boot();let C=new H(B);O(()=>C.stop());try{await C.start()}catch(G){if(!(G instanceof F))throw G;return console.error(G.message),1}return}U().then((y)=>{if(y!==void 0)process.exit(y)},(y)=>{console.error("[gemi] The queue worker failed to start:",y),process.exit(1)});
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=1ACF53BA60E3CBB764756E2164756E21
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"/**\n * The entry point `gemi queue:work` spawns.\n *\n * Exposed as `gemi/queue/work` and resolved by the CLI out of the\n * *application's* `node_modules`, for the reason `gemi/console/run` is: the\n * application's kernel, providers and jobs are built from its copy of gemi,\n * and the worker that drives them should be the same copy, not one bundled\n * into the CLI.\n *\n * Everything worth testing is in `QueueWorker`; this file is the order the\n * process does things in.\n */\nimport path from \"node:path\";\n\nimport { installShutdownSignals } from \"../../server/shutdown\";\nimport { projectRoot } from \"../../support/discover\";\nimport { markQueueWorker } from \"./QueueManager\";\nimport { QueueWorker, QueueWorkerRefused, type WorkerKernel } from \"./WorkerProcess\";\n\nasync function main(): Promise<number | undefined> {\n const rootDir = projectRoot();\n // What `Server.start` and `httpProd` set, and for the same readers: a\n // `worker = true` job's thread finds the application through them, and the\n // log provider resolves its paths from `ROOT_DIR`.\n process.env.ROOT_DIR = rootDir;\n process.env.APP_DIR = path.join(rootDir, \"app\");\n // Before the kernel is imported, so no claim rule can be asked first.\n markQueueWorker();\n\n const kernelPath = path.join(rootDir, \"app/kernel/Kernel.ts\");\n const { default: Kernel } = (await import(kernelPath)) as {\n default?: new () => WorkerKernel & { boot(): void };\n };\n if (typeof Kernel !== \"function\") {\n console.error(`[gemi] ${kernelPath} has no default export to boot the worker from.`);\n return 1;\n }\n const kernel = new Kernel();\n kernel.boot();\n\n const worker = new QueueWorker(kernel);\n // Before the boot, as `Server.start` does in production: the boot is the\n // slow part, and a signal that lands in it would otherwise kill the process\n // on the spot. In development too, unlike a server — no `bun --hot` re-runs\n // this, and a Ctrl+C that lets the jobs finish is what a worker is for.\n installShutdownSignals(() => worker.stop());\n\n try {\n await worker.start();\n } catch (error) {\n if (!(error instanceof QueueWorkerRefused)) throw error;\n console.error(error.message);\n return 1;\n }\n // Running: the signal handler exits the process once it has drained.\n return undefined;\n}\n\nmain().then(\n (code) => {\n if (code !== undefined) process.exit(code);\n },\n (error) => {\n console.error(\"[gemi] The queue worker failed to start:\", error);\n process.exit(1);\n },\n);\n",
|
|
6
6
|
"import type { Application, ShutdownReport } from \"../../foundation/Application\";\nimport { markShuttingDown, shutdownSettings, type ShutdownSettings } from \"../../server/shutdown\";\nimport { QueueManager } from \"./QueueManager\";\n\n/** The part of a `Kernel` a worker drives. */\nexport type WorkerKernel = {\n readonly app: Application;\n waitForBoot(): Promise<void>;\n shutdown(options?: { timeoutMs?: number }): Promise<ShutdownReport>;\n};\n\n/**\n * A worker that was told to start in an application it cannot claim for. The\n * message is written for the operator reading the deploy's logs.\n */\nexport class QueueWorkerRefused extends Error {\n name = \"QueueWorkerRefused\";\n}\n\n/**\n * The process `gemi queue:work` runs: the application booted as a server boots\n * it, claiming from the queue, and no `Bun.serve`. It exists so job capacity\n * can be scaled apart from request traffic, which needs a driver both kinds of\n * process can reach; see `start` for why the memory driver is refused.\n *\n * The caller marks the process as a worker (`markQueueWorker`) before the\n * kernel registers, so every claim rule that asks `claimsInThisProcess` sees a\n * process that claims, whatever `GEMI_QUEUE_CLAIM` says.\n */\nexport class QueueWorker {\n private stopping: Promise<number> | undefined;\n private keepAlive: ReturnType<typeof setInterval> | undefined;\n private readonly settings: ShutdownSettings;\n\n /**\n * `settings` default to the `GEMI_SHUTDOWN_*` variables, read here rather\n * than at the signal so a bad value is warned about while the deploy is\n * being watched, as `Server.start` does.\n */\n constructor(\n private readonly kernel: WorkerKernel,\n settings: Partial<ShutdownSettings> = {},\n ) {\n this.settings = { ...shutdownSettings(), ...settings };\n }\n\n /**\n * Boots the application and starts claiming. Rejects with\n * `QueueWorkerRefused` when the application has no queue, or its queue uses\n * the memory driver.\n *\n * Refused rather than warned about, because a memory worker can never do\n * anything: its jobs live in a `Map` in the process that dispatched them,\n * so a worker's is always empty. Left running, it looks like a healthy\n * deploy — a process up, no errors — that runs nothing, and scaling it out\n * adds no capacity. An exit the platform reports as a crash loop is a form\n * of the mistake someone will see.\n */\n async start(): Promise<void> {\n await this.kernel.waitForBoot();\n // A signal during the boot has already drained and cleared the handle\n // below. Going on would start the loop again and arm a handle nothing\n // clears, holding open a worker that has finished shutting down.\n if (this.stopping) return;\n\n const application = this.kernel.app;\n // `bound`, not `make` in a try: an application built without the queue\n // provider is a configuration to name, not an unbound-token stack trace.\n if (!application.bound(QueueManager)) {\n throw new QueueWorkerRefused(\n \"[gemi] `gemi queue:work` has no queue to claim from: this application \" +\n \"does not register QueueServiceProvider.\",\n );\n }\n const queue = application.make(QueueManager);\n if (!queue.durable) {\n throw new QueueWorkerRefused(\n \"[gemi] `gemi queue:work` refuses to start: the queue uses the memory \" +\n \"driver, which keeps each job in the process that dispatched it, so \" +\n 'a worker never sees one. Set `driver: \"database\"` (or another driver ' +\n \"every process can reach) in app/config/queue.ts, or run jobs in the \" +\n \"server and drop the worker.\",\n );\n }\n\n // Idempotent: a production boot with a durable driver has already started\n // it (`startClaimingIfServing`). Development has not, and a worker claims\n // in either.\n queue.start();\n // The queue's poll timer is unref'd, so that a script's queue does not\n // hold it open; here the queue is the process, and without a handle of its\n // own an idle worker would exit 0 as soon as it booted.\n this.keepAlive = setInterval(() => {}, 1 << 30);\n console.log(\n `[gemi] Queue worker started: claiming up to ${queue.config.concurrency} job(s) at a time.`,\n );\n }\n\n /**\n * Stops claiming, waits for the running jobs, runs every provider's\n * `shutdown()`, and resolves with the exit code: 0 when no job was left\n * running and every provider finished in time, 1 otherwise. Idempotent.\n *\n * `gemi start`'s drain, with the jobs where the requests were:\n * `isShuttingDown()` turns true, which stops a durable queue claiming;\n * running jobs get `timeoutMs` (`GEMI_SHUTDOWN_TIMEOUT`), which a server\n * spends on requests; then `Application.shutdown` gets `providerTimeoutMs`,\n * and in it the queue provider waits for whatever is still running and\n * names it. The two budgets add up as they do for a server, so a worker\n * fits the same grace period. `delayMs` is not waited: it is for a load\n * balancer, and nothing routes to a worker.\n */\n stop(settings: Partial<ShutdownSettings> = {}): Promise<number> {\n this.stopping ??= this.drain({ ...this.settings, ...settings });\n return this.stopping;\n }\n\n private async drain(settings: ShutdownSettings): Promise<number> {\n markShuttingDown();\n const application = this.kernel.app;\n // Resolving the manager now would build a driver only to stop it, which\n // is what a signal during the boot, before the provider resolved it, finds.\n const queue = application.resolved(QueueManager) ? application.make(QueueManager) : undefined;\n if (queue) {\n console.log(\n `[gemi] Shutting down: waiting for ${queue.running} running job(s) ` +\n `(up to ${settings.timeoutMs / 1000}s).`,\n );\n await queue.drain(settings.timeoutMs);\n }\n\n const report = await this.kernel.shutdown({ timeoutMs: settings.providerTimeoutMs });\n clearInterval(this.keepAlive);\n const clean =\n (queue?.running ?? 0) === 0 && report.failed.length === 0 && report.timedOut.length === 0;\n console.log(`[gemi] Shutdown ${clean ? \"complete\" : \"finished with errors\"}.`);\n return clean ? 0 : 1;\n }\n}\n"
|
|
7
7
|
],
|
|
8
|
-
"mappings": ";
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": ";iZAYA,kBCGO,IAAM,QAA2B,GAAM,DAC5C,GAAO,kBACT,DAYO,IAAM,CAAY,CAWJ,OAVX,SACA,UACS,SAOjB,WAAW,CACQ,EACjB,EAAsC,CAAC,EACvC,CAFiB,cAGjB,KAAK,SAAW,IAAK,EAAiB,KAAM,CAAS,OAejD,MAAK,EAAkB,CAK3B,GAJA,MAAM,KAAK,OAAO,YAAY,EAI1B,KAAK,SAAU,OAEnB,IAAM,EAAc,KAAK,OAAO,IAGhC,GAAI,CAAC,EAAY,MAAM,CAAY,EACjC,MAAM,IAAI,EACR,+GAEF,EAEF,IAAM,EAAQ,EAAY,KAAK,CAAY,EAC3C,GAAI,CAAC,EAAM,QACT,MAAM,IAAI,EACR,8SAKF,EAMF,EAAM,MAAM,EAIZ,KAAK,UAAY,YAAY,IAAM,GAAI,UAAO,EAC9C,QAAQ,IACN,+CAA+C,EAAM,OAAO,+BAC9D,EAiBF,IAAI,CAAC,EAAsC,CAAC,EAAoB,CAE9D,OADA,KAAK,WAAa,KAAK,MAAM,IAAK,KAAK,YAAa,CAAS,CAAC,EACvD,KAAK,cAGA,MAAK,CAAC,EAA6C,CAC/D,EAAiB,EACjB,IAAM,EAAc,KAAK,OAAO,IAG1B,EAAQ,EAAY,SAAS,CAAY,EAAI,EAAY,KAAK,CAAY,EAAI,OACpF,GAAI,EACF,QAAQ,IACN,qCAAqC,EAAM,iCAC/B,EAAS,UAAY,SACnC,EACA,MAAM,EAAM,MAAM,EAAS,SAAS,EAGtC,IAAM,EAAS,MAAM,KAAK,OAAO,SAAS,CAAE,UAAW,EAAS,iBAAkB,CAAC,EACnF,cAAc,KAAK,SAAS,EAC5B,IAAM,GACH,GAAO,SAAW,KAAO,GAAK,EAAO,OAAO,SAAW,GAAK,EAAO,SAAS,SAAW,EAE1F,OADA,QAAQ,IAAI,mBAAmB,EAAQ,WAAa,yBAAyB,EACtE,EAAQ,EAAI,EAEvB,CDvHA,eAAe,CAAI,EAAgC,CACjD,IAAM,EAAU,EAAY,EAI5B,QAAQ,IAAI,SAAW,EACvB,QAAQ,IAAI,QAAU,EAAK,KAAK,EAAS,KAAK,EAE9C,EAAgB,EAEhB,IAAM,EAAa,EAAK,KAAK,EAAS,sBAAsB,GACpD,QAAS,GAAY,MAAa,UAG1C,GAAI,OAAO,IAAW,WAEpB,OADA,QAAQ,MAAM,UAAU,kDAA2D,EAC5E,EAET,IAAM,EAAS,IAAI,EACnB,EAAO,KAAK,EAEZ,IAAM,EAAS,IAAI,EAAY,CAAM,EAKrC,EAAuB,IAAM,EAAO,KAAK,CAAC,EAE1C,GAAI,CACF,MAAM,EAAO,MAAM,EACnB,MAAO,EAAO,CACd,GAAI,EAAE,aAAiB,GAAqB,MAAM,EAElD,OADA,QAAQ,MAAM,EAAM,OAAO,EACpB,EAGT,OAGF,EAAK,EAAE,KACL,CAAC,IAAS,CACR,GAAI,IAAS,OAAW,QAAQ,KAAK,CAAI,GAE3C,CAAC,IAAU,CACT,QAAQ,MAAM,2CAA4C,CAAK,EAC/D,QAAQ,KAAK,CAAC,EAElB",
|
|
9
|
+
"debugId": "1ACF53BA60E3CBB764756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
package/dist/support/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{fc as Y}from"../chunk-7kedxtbp.js";import{vg as M}from"../chunk-3fr22rtg.js";import{Fg as P,Hg as R}from"../chunk-7hfv5n00.js";import"../chunk-qxda7pzm.js";import{Qg as Q,Rg as U,Sg as V,Tg as W}from"../chunk-kzh8bkg5.js";import"../chunk-j2nx0dtq.js";class S{static token;async boot(){}static inject(){if(!this.token)throw Error(`Service [${this.name}] does not declare a \`static token\`, so the container has no key to resolve it by.`);try{return R(this)}catch(x){throw Error(`Could not inject [${this.name}]. Services are constructed when the kernel boots, so `+"inject() only works from code that runs after that \u2014 a constructor default or a method "+`body, never module top level. Check that [${this.name}] is listed in \`services\` on your Kernel.`,{cause:x})}}static with(x){let f=new this;for(let[C,g]of Object.entries(x))if(g!==void 0)f[C]=g;return f}}import{readdir as z}from"fs/promises";import{join as B,parse as j}from"path";var H=[".ts",".tsx",".js",".mjs",".jsx"];function J(x={}){let f={};for(let[C,g]of Object.entries(x))f[C]=q(g);return new P(f)}async function L(x,f=new P){let C=[];try{C=await z(x)}catch(D){return f}let g=C.filter((D)=>{let{ext:v,name:F}=j(D);return H.includes(v)&&!F.startsWith(".")}).sort();for(let D of g){let{name:v}=j(D),F=await import(B(x,D));f.set(v,q(F))}return f}function q(x){if(x&&typeof x==="object"&&"default"in x)return x.default;return x}export{M as withDefaults,Q as sourceFiles,W as projectRoot,L as loadConfigFrom,V as discoverClasses,J as createConfigRepository,Y as ServiceProvider,S as Service,P as Repository,U as DiscoveryError};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=8F48516D7E7C7EEB64756E2164756E21
|