@c9up/bay 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -1
- package/dist/BayProvider.d.ts +24 -30
- package/dist/BayProvider.d.ts.map +1 -1
- package/dist/BayProvider.js +58 -9
- package/dist/BayProvider.js.map +1 -1
- package/dist/QueueManager.d.ts +7 -5
- package/dist/QueueManager.d.ts.map +1 -1
- package/dist/QueueManager.js +75 -31
- package/dist/QueueManager.js.map +1 -1
- package/dist/configure.d.ts +18 -0
- package/dist/configure.d.ts.map +1 -0
- package/dist/configure.js +31 -0
- package/dist/configure.js.map +1 -0
- package/dist/drivers/RedisDriver.d.ts +6 -0
- package/dist/drivers/RedisDriver.d.ts.map +1 -1
- package/dist/drivers/RedisDriver.js +49 -17
- package/dist/drivers/RedisDriver.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/nodeEnv.d.ts +16 -0
- package/dist/nodeEnv.d.ts.map +1 -0
- package/dist/nodeEnv.js +32 -0
- package/dist/nodeEnv.js.map +1 -0
- package/dist/services/main.d.ts +5 -0
- package/dist/services/main.d.ts.map +1 -1
- package/dist/services/main.js +7 -0
- package/dist/services/main.js.map +1 -1
- package/dist/stores.d.ts +41 -0
- package/dist/stores.d.ts.map +1 -0
- package/dist/stores.js +46 -0
- package/dist/stores.js.map +1 -0
- package/package.json +5 -1
- package/src/BayProvider.ts +84 -19
- package/src/QueueManager.ts +77 -32
- package/src/configure.ts +45 -0
- package/src/drivers/RedisDriver.ts +69 -22
- package/src/index.ts +1 -0
- package/src/nodeEnv.ts +30 -0
- package/src/services/main.ts +8 -0
- package/src/stores.ts +59 -0
package/README.md
CHANGED
|
@@ -11,9 +11,14 @@ pnpm add @c9up/bay
|
|
|
11
11
|
ream configure @c9up/bay
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
+
`ream add @c9up/bay` installs it, registers the provider and writes
|
|
15
|
+
`config/queue.ts`. The rest of this page assumes that has run.
|
|
16
|
+
|
|
14
17
|
## Usage
|
|
15
18
|
|
|
16
|
-
Register the provider
|
|
19
|
+
Register the provider, then name the queue backend in `config/queue.ts` — the
|
|
20
|
+
provider reads `config.get('queue')`, so a `config/bay.ts` would be loaded under
|
|
21
|
+
the key `bay` and never seen:
|
|
17
22
|
|
|
18
23
|
```ts
|
|
19
24
|
// reamrc.ts
|
|
@@ -22,6 +27,66 @@ providers: [
|
|
|
22
27
|
]
|
|
23
28
|
```
|
|
24
29
|
|
|
30
|
+
```ts
|
|
31
|
+
// config/queue.ts
|
|
32
|
+
import { defineConfig, stores } from '@c9up/bay'
|
|
33
|
+
import env from '#start/env'
|
|
34
|
+
|
|
35
|
+
export default defineConfig({
|
|
36
|
+
default: env.get('QUEUE_STORE'),
|
|
37
|
+
stores: {
|
|
38
|
+
memory: stores.memory(),
|
|
39
|
+
redis: stores.redis({ connection: 'main' }),
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
// start/queue.ts
|
|
46
|
+
import queue from '@c9up/bay/services/main'
|
|
47
|
+
|
|
48
|
+
queue.register('send-email', new SendEmailJob())
|
|
49
|
+
await queue.dispatch('send-email', { to: 'user@example.com' })
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
| Store | Keeps jobs | Use it when |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| `stores.memory()` | until the process exits | tests, and local work |
|
|
55
|
+
| `stores.redis({ connection })` | in Redis | anything that must survive a restart |
|
|
56
|
+
|
|
57
|
+
Factories are lazy: only the store actually selected is built, so naming a Redis
|
|
58
|
+
queue in a config that runs in memory opens no connection. A `default` that
|
|
59
|
+
names nothing throws, listing what exists — falling back to memory would look
|
|
60
|
+
like it worked until a restart dropped every pending job.
|
|
61
|
+
|
|
62
|
+
`stores.redis` takes a `@c9up/quasar` connection name, resolved at first use so
|
|
63
|
+
bay never imports quasar, which stays an optional peer. Pass an ioredis-shaped
|
|
64
|
+
client (or a function answering one) to use any other.
|
|
65
|
+
|
|
66
|
+
## Delivery guarantee, and the one way to lose it
|
|
67
|
+
|
|
68
|
+
A job the queue accepted gets run: `pop()` moves it from pending to processing
|
|
69
|
+
in a single `LMOVE`, so a worker that dies mid-job leaves the job recoverable
|
|
70
|
+
rather than gone.
|
|
71
|
+
|
|
72
|
+
`LMOVE` needs **Redis 6.2 or later**. Without it the move is `lpop` then
|
|
73
|
+
`rpush`, and a crash between the two deletes the job from pending before it
|
|
74
|
+
reaches processing — nothing recovers it, because nothing knows it existed.
|
|
75
|
+
That turns at-least-once delivery into at-most-once.
|
|
76
|
+
|
|
77
|
+
So on an older Redis the driver **refuses to start in production**, and says
|
|
78
|
+
which two ways out there are:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
// Either upgrade the server, or state that losing a job is acceptable here:
|
|
82
|
+
stores.redis({ connection: 'jobs', allowNonAtomicPop: true })
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The opt-in is honoured and still logs a warning on every process that starts
|
|
86
|
+
with it, naming production — agreeing once in a config file is not the same as
|
|
87
|
+
being reminded, in the logs of an incident, that this is how the process was
|
|
88
|
+
running. Outside production the fallback simply warns.
|
|
89
|
+
|
|
25
90
|
## Entry points
|
|
26
91
|
|
|
27
92
|
- `@c9up/bay` — main API
|
package/dist/BayProvider.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { QueueStoreFactory } from "./stores.js";
|
|
1
2
|
/**
|
|
2
3
|
* Slim, duck-typed host context — bay stays publishable without
|
|
3
4
|
* importing `@c9up/ream`. Any framework that exposes a Container with
|
|
@@ -17,44 +18,37 @@ export interface BayAppContext {
|
|
|
17
18
|
}
|
|
18
19
|
export interface BayProviderConfig {
|
|
19
20
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
*
|
|
27
|
-
*
|
|
21
|
+
* Which named store to use — a key of {@link stores}. Read from the
|
|
22
|
+
* environment in the generated config, so a deployment picks its queue
|
|
23
|
+
* backend without editing a file.
|
|
24
|
+
*/
|
|
25
|
+
default?: string;
|
|
26
|
+
/**
|
|
27
|
+
* The queue stores this application can use, by name. Each is a factory
|
|
28
|
+
* from `stores.*`, built only when it is the one selected.
|
|
29
|
+
*/
|
|
30
|
+
stores?: Record<string, QueueStoreFactory>;
|
|
31
|
+
/**
|
|
32
|
+
* The single-store form, kept for configs written against it: only
|
|
33
|
+
* `"memory"` was ever accepted. Prefer `default` + `stores`, which is how a
|
|
34
|
+
* pluggable backend is configured everywhere else and what lets the
|
|
35
|
+
* environment choose.
|
|
28
36
|
*/
|
|
29
37
|
driver?: "memory";
|
|
30
38
|
}
|
|
31
|
-
/**
|
|
32
|
-
* BayProvider — registers a default in-memory `QueueManager` in the
|
|
33
|
-
* host container so apps that don't need custom driver wiring can
|
|
34
|
-
* `import queue from '@c9up/bay/services/main'` and dispatch
|
|
35
|
-
* straight away. Job handlers are still registered manually via
|
|
36
|
-
* `queue.register(name, handler)` — that's intrinsic to the queue
|
|
37
|
-
* design (handlers are app-defined, not config-driven).
|
|
38
|
-
*
|
|
39
|
-
* Apps with non-trivial wiring (Redis driver, custom queue config)
|
|
40
|
-
* can ignore this provider and bind their own `QueueManager` instance
|
|
41
|
-
* in the container; the `services/main` proxy resolves whatever is
|
|
42
|
-
* registered.
|
|
43
|
-
*
|
|
44
|
-
* // reamrc.ts
|
|
45
|
-
* providers: [() => import('@c9up/bay/provider')]
|
|
46
|
-
*
|
|
47
|
-
* // start/queue.ts
|
|
48
|
-
* import queue from '@c9up/bay/services/main'
|
|
49
|
-
*
|
|
50
|
-
* queue.register('send-email', new SendEmailJob())
|
|
51
|
-
* await queue.dispatch('send-email', { to: 'user@example.com' })
|
|
52
|
-
*/
|
|
53
39
|
export default class BayProvider {
|
|
40
|
+
#private;
|
|
54
41
|
protected app: BayAppContext;
|
|
55
42
|
constructor(app: BayAppContext);
|
|
56
43
|
register(): void;
|
|
57
44
|
boot(): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Stop the worker the app started, and let the job in flight finish.
|
|
47
|
+
*
|
|
48
|
+
* A worker polls on a timer. Left running, it survives a dev reload, a test
|
|
49
|
+
* teardown and a SIGTERM — so the old process keeps pulling jobs the new
|
|
50
|
+
* one is also pulling, and the same job runs twice.
|
|
51
|
+
*/
|
|
58
52
|
shutdown(): Promise<void>;
|
|
59
53
|
}
|
|
60
54
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BayProvider.d.ts","sourceRoot":"","sources":["../src/BayProvider.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,UAAU,YAAY;IACrB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,GAAG,IAAI,CAAC;IACxD,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACjD;AACD,UAAU,cAAc;IACvB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;CAC7C;AACD,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,YAAY,CAAC;IACxB,MAAM,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IACjC
|
|
1
|
+
{"version":3,"file":"BayProvider.d.ts","sourceRoot":"","sources":["../src/BayProvider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;GAKG;AACH,UAAU,YAAY;IACrB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,GAAG,IAAI,CAAC;IACxD,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACjD;AACD,UAAU,cAAc;IACvB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;CAC7C;AACD,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,YAAY,CAAC;IACxB,MAAM,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC3C;;;;;OAKG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC;CAClB;AAoED,MAAM,CAAC,OAAO,OAAO,WAAW;;IACnB,SAAS,CAAC,GAAG,EAAE,aAAa;gBAAlB,GAAG,EAAE,aAAa;IAExC,QAAQ,IAAI,IAAI;IAaV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B;;;;;;OAMG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAS/B"}
|
package/dist/BayProvider.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MemoryDriver } from "./drivers/MemoryDriver.js";
|
|
2
2
|
import { QueueManager } from "./QueueManager.js";
|
|
3
|
-
import { setQueue } from "./services/main.js";
|
|
3
|
+
import { clearQueue, getQueue, setQueue } from "./services/main.js";
|
|
4
4
|
/**
|
|
5
5
|
* BayProvider — registers a default in-memory `QueueManager` in the
|
|
6
6
|
* host container so apps that don't need custom driver wiring can
|
|
@@ -23,6 +23,40 @@ import { setQueue } from "./services/main.js";
|
|
|
23
23
|
* queue.register('send-email', new SendEmailJob())
|
|
24
24
|
* await queue.dispatch('send-email', { to: 'user@example.com' })
|
|
25
25
|
*/
|
|
26
|
+
/**
|
|
27
|
+
* The driver the config asks for.
|
|
28
|
+
*
|
|
29
|
+
* `default` + `stores` first — the form an environment variable can steer. The
|
|
30
|
+
* `driver` key is the single-store form kept for configs written against it.
|
|
31
|
+
* Naming a store that does not exist throws rather than falling back to memory:
|
|
32
|
+
* an application that meant to queue in Redis and silently got an in-process
|
|
33
|
+
* queue would only find out when a restart dropped every pending job.
|
|
34
|
+
*/
|
|
35
|
+
function buildDriver(config) {
|
|
36
|
+
const stores = config?.stores;
|
|
37
|
+
const name = config?.default;
|
|
38
|
+
if (stores && name !== undefined) {
|
|
39
|
+
const selected = stores[name];
|
|
40
|
+
if (!selected) {
|
|
41
|
+
const known = Object.keys(stores);
|
|
42
|
+
throw new Error(`[bay] config.queue names the store '${name}', which is not in \`stores\`. ` +
|
|
43
|
+
(known.length > 0
|
|
44
|
+
? `Declared: ${known.join(", ")}.`
|
|
45
|
+
: "`stores` is empty — declare one with stores.memory() or stores.redis()."));
|
|
46
|
+
}
|
|
47
|
+
return selected();
|
|
48
|
+
}
|
|
49
|
+
if (stores && name === undefined) {
|
|
50
|
+
throw new Error("[bay] config.queue declares `stores` but no `default` naming which one to use. " +
|
|
51
|
+
`Set default to one of: ${Object.keys(stores).join(", ")}.`);
|
|
52
|
+
}
|
|
53
|
+
const driverName = config?.driver ?? "memory";
|
|
54
|
+
if (driverName !== "memory") {
|
|
55
|
+
throw new Error(`[bay] Unsupported driver '${driverName}' — name it under \`stores\` instead: ` +
|
|
56
|
+
"stores: { redis: stores.redis({ connection: 'main' }) }.");
|
|
57
|
+
}
|
|
58
|
+
return new MemoryDriver();
|
|
59
|
+
}
|
|
26
60
|
export default class BayProvider {
|
|
27
61
|
app;
|
|
28
62
|
constructor(app) {
|
|
@@ -31,20 +65,35 @@ export default class BayProvider {
|
|
|
31
65
|
register() {
|
|
32
66
|
this.app.container.singleton(QueueManager, () => {
|
|
33
67
|
const config = this.app.config.get("queue");
|
|
34
|
-
|
|
35
|
-
if (driverName !== "memory") {
|
|
36
|
-
throw new Error(`[bay] Unsupported driver '${driverName}' for default provider — ` +
|
|
37
|
-
"wire QueueManager yourself in start/queue.ts for non-memory drivers.");
|
|
38
|
-
}
|
|
39
|
-
return new QueueManager(new MemoryDriver());
|
|
68
|
+
return new QueueManager(buildDriver(config));
|
|
40
69
|
});
|
|
41
70
|
this.app.container.singleton("queue", () => this.app.container.resolve(QueueManager));
|
|
42
71
|
}
|
|
72
|
+
/** The queue THIS provider booted — not whatever the module singleton holds. */
|
|
73
|
+
#queue;
|
|
43
74
|
async boot() {
|
|
44
75
|
// Populate the `@c9up/bay/services/main` singleton so apps can
|
|
45
76
|
// `import queue from '@c9up/bay/services/main'` from anywhere.
|
|
46
|
-
|
|
77
|
+
this.#queue = await this.app.container.resolve(QueueManager);
|
|
78
|
+
setQueue(this.#queue);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Stop the worker the app started, and let the job in flight finish.
|
|
82
|
+
*
|
|
83
|
+
* A worker polls on a timer. Left running, it survives a dev reload, a test
|
|
84
|
+
* teardown and a SIGTERM — so the old process keeps pulling jobs the new
|
|
85
|
+
* one is also pulling, and the same job runs twice.
|
|
86
|
+
*/
|
|
87
|
+
async shutdown() {
|
|
88
|
+
if (!this.#queue)
|
|
89
|
+
return;
|
|
90
|
+
await this.#queue.stop();
|
|
91
|
+
// Two applications can share a process — parallel tests, a hot reload.
|
|
92
|
+
// The module singleton holds whichever booted last, so it is only ours
|
|
93
|
+
// to clear while it still points at the queue this provider booted.
|
|
94
|
+
if (getQueue() === this.#queue)
|
|
95
|
+
clearQueue();
|
|
96
|
+
this.#queue = undefined;
|
|
47
97
|
}
|
|
48
|
-
async shutdown() { }
|
|
49
98
|
}
|
|
50
99
|
//# sourceMappingURL=BayProvider.js.map
|
package/dist/BayProvider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BayProvider.js","sourceRoot":"","sources":["../src/BayProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"BayProvider.js","sourceRoot":"","sources":["../src/BayProvider.ts"],"names":[],"mappings":"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"}
|
package/dist/QueueManager.d.ts
CHANGED
|
@@ -37,10 +37,6 @@ export interface QueueDriver {
|
|
|
37
37
|
}
|
|
38
38
|
export declare class QueueManager {
|
|
39
39
|
#private;
|
|
40
|
-
private driver;
|
|
41
|
-
private handlers;
|
|
42
|
-
private running;
|
|
43
|
-
private inflightPromise;
|
|
44
40
|
constructor(driver: QueueDriver);
|
|
45
41
|
/** Register a job handler. */
|
|
46
42
|
register(name: string, handler: JobHandler | (new () => JobHandler)): void;
|
|
@@ -66,7 +62,13 @@ export declare class QueueManager {
|
|
|
66
62
|
recoverStale(): Promise<number>;
|
|
67
63
|
/** Await the currently in-flight processOne, if any. */
|
|
68
64
|
drain(): Promise<void>;
|
|
69
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* Stop the worker and wait for it to actually be gone.
|
|
67
|
+
*
|
|
68
|
+
* Awaits the LOOP, not just the job in flight: a stop that returns while
|
|
69
|
+
* the loop is still sleeping leaves a worker running past the teardown that
|
|
70
|
+
* asked it to stop.
|
|
71
|
+
*/
|
|
70
72
|
stop(): Promise<void>;
|
|
71
73
|
/** Get failed jobs. */
|
|
72
74
|
failedJobs(): Promise<Job[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueueManager.d.ts","sourceRoot":"","sources":["../src/QueueManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,GAAG;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IAC1B,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,GAAG,IAAI,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzB,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB;;;;OAIG;IACH,YAAY,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACjC;AAED,qBAAa,YAAY;;
|
|
1
|
+
{"version":3,"file":"QueueManager.d.ts","sourceRoot":"","sources":["../src/QueueManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,GAAG;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IAC1B,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,GAAG,IAAI,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzB,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB;;;;OAIG;IACH,YAAY,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACjC;AAED,qBAAa,YAAY;;gBAUZ,MAAM,EAAE,WAAW;IAI/B,8BAA8B;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,CAAC,UAAU,UAAU,CAAC,GAAG,IAAI;IAI1E,mCAAmC;IAC7B,QAAQ,CACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAChC,OAAO,CAAC,MAAM,CAAC;IAkBlB,yCAAyC;IACnC,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IA2CpC;;;;;OAKG;IACG,IAAI,CAAC,cAAc,SAAO,EAAE,cAAc,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IA6EzE;;;;;OAKG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAIrC,wDAAwD;IAClD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B;;;;;;OAMG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,uBAAuB;IACjB,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAIlC,sBAAsB;IAChB,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;CAG7B"}
|
package/dist/QueueManager.js
CHANGED
|
@@ -7,16 +7,20 @@
|
|
|
7
7
|
* queue.work()
|
|
8
8
|
*/
|
|
9
9
|
export class QueueManager {
|
|
10
|
-
driver;
|
|
11
|
-
handlers = new Map();
|
|
12
|
-
running = false;
|
|
13
|
-
|
|
10
|
+
#driver;
|
|
11
|
+
#handlers = new Map();
|
|
12
|
+
#running = false;
|
|
13
|
+
/** The running loop, so `stop()` can wait for it to finish. */
|
|
14
|
+
#loopPromise;
|
|
15
|
+
/** Cuts the sleep between polls short. */
|
|
16
|
+
#wake;
|
|
17
|
+
#inflightPromise = null;
|
|
14
18
|
constructor(driver) {
|
|
15
|
-
this
|
|
19
|
+
this.#driver = driver;
|
|
16
20
|
}
|
|
17
21
|
/** Register a job handler. */
|
|
18
22
|
register(name, handler) {
|
|
19
|
-
this
|
|
23
|
+
this.#handlers.set(name, handler);
|
|
20
24
|
}
|
|
21
25
|
/** Dispatch a job to the queue. */
|
|
22
26
|
async dispatch(name, payload, options) {
|
|
@@ -33,18 +37,18 @@ export class QueueManager {
|
|
|
33
37
|
status: "pending",
|
|
34
38
|
createdAt: Date.now(),
|
|
35
39
|
};
|
|
36
|
-
await this
|
|
40
|
+
await this.#driver.push(job);
|
|
37
41
|
return id;
|
|
38
42
|
}
|
|
39
43
|
/** Process the next job in the queue. */
|
|
40
44
|
async processOne() {
|
|
41
|
-
const job = await this
|
|
45
|
+
const job = await this.#driver.pop();
|
|
42
46
|
if (!job)
|
|
43
47
|
return false;
|
|
44
|
-
const handlerOrClass = this
|
|
48
|
+
const handlerOrClass = this.#handlers.get(job.name);
|
|
45
49
|
if (!handlerOrClass) {
|
|
46
50
|
process.stderr.write(`QueueManager: no handler registered for job '${job.name}'\n`);
|
|
47
|
-
await this
|
|
51
|
+
await this.#driver.fail(job, `No handler registered for job: ${job.name}`);
|
|
48
52
|
return true;
|
|
49
53
|
}
|
|
50
54
|
const handler = typeof handlerOrClass === "function"
|
|
@@ -56,18 +60,18 @@ export class QueueManager {
|
|
|
56
60
|
try {
|
|
57
61
|
await handler.handle(job.payload);
|
|
58
62
|
job.status = "completed";
|
|
59
|
-
await this
|
|
63
|
+
await this.#driver.complete(job);
|
|
60
64
|
}
|
|
61
65
|
catch (err) {
|
|
62
66
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
63
67
|
if (job.attempts < job.maxAttempts) {
|
|
64
68
|
job.status = "pending";
|
|
65
|
-
await this
|
|
69
|
+
await this.#driver.retry(job);
|
|
66
70
|
}
|
|
67
71
|
else {
|
|
68
72
|
job.status = "failed";
|
|
69
73
|
job.error = errorMsg;
|
|
70
|
-
await this
|
|
74
|
+
await this.#driver.fail(job, errorMsg);
|
|
71
75
|
}
|
|
72
76
|
}
|
|
73
77
|
return true;
|
|
@@ -85,33 +89,64 @@ export class QueueManager {
|
|
|
85
89
|
if (recoverStaleMs <= 0) {
|
|
86
90
|
throw new Error("recoverStaleMs must be positive");
|
|
87
91
|
}
|
|
88
|
-
if (this
|
|
92
|
+
if (this.#running) {
|
|
89
93
|
throw new Error("QueueManager is already running");
|
|
90
94
|
}
|
|
91
|
-
this
|
|
95
|
+
this.#running = true;
|
|
96
|
+
const loop = this.#loop(pollIntervalMs, recoverStaleMs);
|
|
97
|
+
this.#loopPromise = loop;
|
|
98
|
+
try {
|
|
99
|
+
await loop;
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
this.#loopPromise = undefined;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The polling loop itself.
|
|
107
|
+
*
|
|
108
|
+
* Between jobs it sleeps, and that sleep is CANCELLABLE: `stop()` wakes it
|
|
109
|
+
* rather than waiting out the interval. Without that, stopping returned
|
|
110
|
+
* while the loop was still pending — up to a full poll interval of a worker
|
|
111
|
+
* that was supposed to be gone, and a timer holding the process open.
|
|
112
|
+
*/
|
|
113
|
+
async #loop(pollIntervalMs, recoverStaleMs) {
|
|
92
114
|
await this.#tryRecoverStale();
|
|
93
115
|
let lastRecover = Date.now();
|
|
94
|
-
while (this
|
|
116
|
+
while (this.#running) {
|
|
95
117
|
try {
|
|
96
|
-
this
|
|
97
|
-
const processed = await this
|
|
98
|
-
if (!processed)
|
|
99
|
-
await
|
|
100
|
-
}
|
|
118
|
+
this.#inflightPromise = this.processOne();
|
|
119
|
+
const processed = await this.#inflightPromise;
|
|
120
|
+
if (!processed)
|
|
121
|
+
await this.#sleep(pollIntervalMs);
|
|
101
122
|
}
|
|
102
123
|
catch (err) {
|
|
103
124
|
process.stderr.write(`QueueManager processOne error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
104
|
-
await
|
|
125
|
+
await this.#sleep(pollIntervalMs);
|
|
105
126
|
}
|
|
106
127
|
finally {
|
|
107
|
-
this
|
|
128
|
+
this.#inflightPromise = null;
|
|
108
129
|
}
|
|
109
|
-
if (this
|
|
130
|
+
if (this.#running && Date.now() - lastRecover >= recoverStaleMs) {
|
|
110
131
|
await this.#tryRecoverStale();
|
|
111
132
|
lastRecover = Date.now();
|
|
112
133
|
}
|
|
113
134
|
}
|
|
114
135
|
}
|
|
136
|
+
/** Wait, unless `stop()` says otherwise first. */
|
|
137
|
+
#sleep(ms) {
|
|
138
|
+
return new Promise((resolve) => {
|
|
139
|
+
const timer = setTimeout(() => {
|
|
140
|
+
this.#wake = undefined;
|
|
141
|
+
resolve();
|
|
142
|
+
}, ms);
|
|
143
|
+
this.#wake = () => {
|
|
144
|
+
clearTimeout(timer);
|
|
145
|
+
this.#wake = undefined;
|
|
146
|
+
resolve();
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
}
|
|
115
150
|
/** recoverStale() wrapper that swallows driver errors — used by the work loop. */
|
|
116
151
|
async #tryRecoverStale() {
|
|
117
152
|
try {
|
|
@@ -128,26 +163,35 @@ export class QueueManager {
|
|
|
128
163
|
* Called automatically by work(); also safe to schedule manually.
|
|
129
164
|
*/
|
|
130
165
|
async recoverStale() {
|
|
131
|
-
return (await this
|
|
166
|
+
return (await this.#driver.recoverStale?.()) ?? 0;
|
|
132
167
|
}
|
|
133
168
|
/** Await the currently in-flight processOne, if any. */
|
|
134
169
|
async drain() {
|
|
135
|
-
if (this
|
|
136
|
-
await this
|
|
170
|
+
if (this.#inflightPromise) {
|
|
171
|
+
await this.#inflightPromise.catch(() => { });
|
|
137
172
|
}
|
|
138
173
|
}
|
|
139
|
-
/**
|
|
174
|
+
/**
|
|
175
|
+
* Stop the worker and wait for it to actually be gone.
|
|
176
|
+
*
|
|
177
|
+
* Awaits the LOOP, not just the job in flight: a stop that returns while
|
|
178
|
+
* the loop is still sleeping leaves a worker running past the teardown that
|
|
179
|
+
* asked it to stop.
|
|
180
|
+
*/
|
|
140
181
|
async stop() {
|
|
141
|
-
this
|
|
182
|
+
this.#running = false;
|
|
183
|
+
this.#wake?.();
|
|
142
184
|
await this.drain();
|
|
185
|
+
if (this.#loopPromise)
|
|
186
|
+
await this.#loopPromise.catch(() => { });
|
|
143
187
|
}
|
|
144
188
|
/** Get failed jobs. */
|
|
145
189
|
async failedJobs() {
|
|
146
|
-
return this
|
|
190
|
+
return this.#driver.failed();
|
|
147
191
|
}
|
|
148
192
|
/** Get queue size. */
|
|
149
193
|
async size() {
|
|
150
|
-
return this
|
|
194
|
+
return this.#driver.size();
|
|
151
195
|
}
|
|
152
196
|
}
|
|
153
197
|
//# sourceMappingURL=QueueManager.js.map
|
package/dist/QueueManager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueueManager.js","sourceRoot":"","sources":["../src/QueueManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkCH,MAAM,OAAO,YAAY;
|
|
1
|
+
{"version":3,"file":"QueueManager.js","sourceRoot":"","sources":["../src/QueueManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ream configure @c9up/bay` — wire the job queue in one command.
|
|
3
|
+
*
|
|
4
|
+
* The provider alone is not enough: it reads `config/queue.ts`, and a package
|
|
5
|
+
* registered without one falls back to a default that is rarely the one an
|
|
6
|
+
* application wants. Writing both together is what makes `ream add` mean
|
|
7
|
+
* installed AND working.
|
|
8
|
+
*/
|
|
9
|
+
interface Codemods {
|
|
10
|
+
addProvider(importPath: string): Promise<void>;
|
|
11
|
+
addEnvVars(vars: Record<string, string>): Promise<void>;
|
|
12
|
+
writeFile(filePath: string, content: string, options?: {
|
|
13
|
+
force?: boolean;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export declare function configure(codemods: Codemods): Promise<void>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=configure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,UAAU,QAAQ;IACjB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,SAAS,CACR,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;CACjB;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBjE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ream configure @c9up/bay` — wire the job queue in one command.
|
|
3
|
+
*
|
|
4
|
+
* The provider alone is not enough: it reads `config/queue.ts`, and a package
|
|
5
|
+
* registered without one falls back to a default that is rarely the one an
|
|
6
|
+
* application wants. Writing both together is what makes `ream add` mean
|
|
7
|
+
* installed AND working.
|
|
8
|
+
*/
|
|
9
|
+
export async function configure(codemods) {
|
|
10
|
+
// The config below reads these, so they are declared here. Writing the file
|
|
11
|
+
// without them leaves an application whose config asks the environment for
|
|
12
|
+
// something nothing ever put there.
|
|
13
|
+
await codemods.addEnvVars({
|
|
14
|
+
QUEUE_STORE: "memory",
|
|
15
|
+
});
|
|
16
|
+
await codemods.addProvider("@c9up/bay/provider");
|
|
17
|
+
await codemods.writeFile("config/queue.ts", `import { defineConfig, stores } from '@c9up/bay'
|
|
18
|
+
import env from '#start/env'
|
|
19
|
+
|
|
20
|
+
export default defineConfig({
|
|
21
|
+
// Which store to run on. Memory forgets everything on restart, which is
|
|
22
|
+
// what a single process in development wants and nothing else does.
|
|
23
|
+
default: env.get('QUEUE_STORE', 'memory'),
|
|
24
|
+
|
|
25
|
+
stores: {
|
|
26
|
+
memory: stores.memory(),
|
|
27
|
+
redis: stores.redis({ connection: 'main' }),
|
|
28
|
+
},
|
|
29
|
+
})`);
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=configure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAkB;IACjD,4EAA4E;IAC5E,2EAA2E;IAC3E,oCAAoC;IACpC,MAAM,QAAQ,CAAC,UAAU,CAAC;QACzB,WAAW,EAAE,QAAQ;KACrB,CAAC,CAAC;IAEH,MAAM,QAAQ,CAAC,WAAW,CAAC,oBAAoB,CAAC,CAAC;IACjD,MAAM,QAAQ,CAAC,SAAS,CACvB,iBAAiB,EACjB;;;;;;;;;;;;GAYC,CACD,CAAC;AACH,CAAC"}
|
|
@@ -41,6 +41,12 @@ export declare class RedisDriver implements QueueDriver {
|
|
|
41
41
|
constructor(source: RedisClientSource, options?: {
|
|
42
42
|
prefix?: string;
|
|
43
43
|
visibilityTimeoutMs?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Accept the non-atomic pop on a Redis older than 6.2, in
|
|
46
|
+
* production. Off by default: losing an accepted job is a choice a
|
|
47
|
+
* deployment makes, not one a version check makes for it.
|
|
48
|
+
*/
|
|
49
|
+
allowNonAtomicPop?: boolean;
|
|
44
50
|
});
|
|
45
51
|
push(job: Job): Promise<void>;
|
|
46
52
|
pop(): Promise<Job | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RedisDriver.d.ts","sourceRoot":"","sources":["../../src/drivers/RedisDriver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;
|
|
1
|
+
{"version":3,"file":"RedisDriver.d.ts","sourceRoot":"","sources":["../../src/drivers/RedisDriver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,WAAW,WAAW;IAC3B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1C,KAAK,CAAC,CACL,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GAAG,OAAO,EACtB,EAAE,EAAE,MAAM,GAAG,OAAO,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACnE,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACpE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3E,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACzC;AAcD;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAC1B,WAAW,GACX,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;AAmD9C,qBAAa,WAAY,YAAW,WAAW;;gBAsC7C,MAAM,EAAE,iBAAiB,EACzB,OAAO,CAAC,EAAE;QACT,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B;;;;WAIG;QACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;KAC5B;IAkCI,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7B,GAAG,IAAI,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAkD1B,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5C,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9B,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IA8D/B,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAexB,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;CAI7B"}
|