@owlmeans/queue 0.1.18-rc.4 → 0.1.18-rc.40
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 +285 -8
- package/agent-meta/manifest.json +9 -2
- package/agent-meta/skills/queue/SKILL.md +241 -12
- package/agent-meta/skills/scheduled-jobs/SKILL.md +151 -0
- package/build/bridge.d.ts +30 -0
- package/build/bridge.d.ts.map +1 -0
- package/build/bridge.js +108 -0
- package/build/bridge.js.map +1 -0
- package/build/config.d.ts +50 -0
- package/build/config.d.ts.map +1 -0
- package/build/config.js +141 -0
- package/build/config.js.map +1 -0
- package/build/consts.d.ts +33 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +35 -0
- package/build/consts.js.map +1 -0
- package/build/errors.d.ts +68 -0
- package/build/errors.d.ts.map +1 -0
- package/build/errors.js +103 -0
- package/build/errors.js.map +1 -0
- package/build/index.d.ts +10 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +10 -1
- package/build/index.js.map +1 -1
- package/build/protocol.d.ts +10 -0
- package/build/protocol.d.ts.map +1 -0
- package/build/protocol.js +56 -0
- package/build/protocol.js.map +1 -0
- package/build/route.d.ts +9 -0
- package/build/route.d.ts.map +1 -0
- package/build/route.js +31 -0
- package/build/route.js.map +1 -0
- package/build/transport.d.ts +15 -0
- package/build/transport.d.ts.map +1 -0
- package/build/transport.js +59 -0
- package/build/transport.js.map +1 -0
- package/build/types.d.ts +309 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/build/types.local.d.ts +3 -0
- package/build/types.local.d.ts.map +1 -0
- package/build/types.local.js +2 -0
- package/build/types.local.js.map +1 -0
- package/build/utils.d.ts +4 -0
- package/build/utils.d.ts.map +1 -0
- package/build/utils.js +4 -0
- package/build/utils.js.map +1 -0
- package/build/worker.d.ts +27 -0
- package/build/worker.d.ts.map +1 -0
- package/build/worker.js +59 -0
- package/build/worker.js.map +1 -0
- package/package.json +13 -3
- package/src/bridge.ts +126 -0
- package/src/config.ts +171 -0
- package/src/consts.ts +38 -0
- package/src/errors.ts +121 -0
- package/src/index.ts +10 -0
- package/src/protocol.ts +74 -0
- package/src/route.ts +40 -0
- package/src/transport.ts +77 -0
- package/src/types.local.ts +3 -0
- package/src/types.ts +323 -0
- package/src/utils.ts +5 -0
- package/src/worker.ts +73 -0
- package/tests/bridge.spec.ts +64 -0
- package/tests/config.spec.ts +66 -0
- package/tests/protocol.spec.ts +58 -0
- package/tests/schedule.spec.ts +100 -0
- package/tsconfig.json +1 -0
- package/build/.gitkeep +0 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scheduled-jobs
|
|
3
|
+
description: Recurring background work on OwlMeans queues — declareSchedule in @owlmeans/queue, reconciled into BullMQ job schedulers by @owlmeans/redis-queue when a listening worker starts. Covers interval vs cron schedules, the processor a sweep runs, overlap and restart semantics, renaming and removing a schedule, multi-replica and rolling-deploy behaviour, and testing. Use when adding a nightly or periodic job, replacing a platform CronJob or a setInterval with a schedule, or diagnosing a schedule that does not run.
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
7
|
+
|
|
8
|
+
# Scheduled jobs
|
|
9
|
+
|
|
10
|
+
**Layer:** Infra · **Packages:** `@owlmeans/queue` (lead — the declaration), `@owlmeans/redis-queue`
|
|
11
|
+
(the reconciliation)
|
|
12
|
+
|
|
13
|
+
A schedule is a declaration that makes the broker produce an ordinary job on an interval or a cron
|
|
14
|
+
pattern. A worker that consumes the queue runs it with a processor. There is no second scheduler
|
|
15
|
+
process, no cron table and no timer in application code.
|
|
16
|
+
|
|
17
|
+
## When a schedule is the answer
|
|
18
|
+
|
|
19
|
+
| Situation | Answer |
|
|
20
|
+
|---|---|
|
|
21
|
+
| Periodic sweep, reconciliation, digest, retention delete, rollup | A schedule on a queue a worker consumes |
|
|
22
|
+
| "Remind this user in 20 minutes" | `JobOptions.delay` on one job — a schedule is not per record |
|
|
23
|
+
| A far-future or cancellable per-record deadline | A row with a due date, swept by one schedule |
|
|
24
|
+
| A deployment that runs no worker | A platform `CronJob` calling a guarded entrypoint |
|
|
25
|
+
| A `setInterval` inside a request handler or a long-lived service | A schedule — the interval dies with the process and runs once per replica |
|
|
26
|
+
|
|
27
|
+
Whether the work belongs on a queue at all is `resource-choice`.
|
|
28
|
+
|
|
29
|
+
## Declaring
|
|
30
|
+
|
|
31
|
+
In the SHARED package every process loads, after the queue:
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
declareQueue(cfg, APP_MAINTENANCE, ['app:maintenance:reconcile', 'app:maintenance:purge'], {
|
|
35
|
+
worker: { concurrency: 1, lockDuration: 60_000 }
|
|
36
|
+
})
|
|
37
|
+
declareSchedule(cfg, {
|
|
38
|
+
id: 'app-nightly-reconcile', queue: APP_MAINTENANCE, name: 'app:maintenance:reconcile',
|
|
39
|
+
pattern: '17 3 * * *', tz: 'UTC', data: {},
|
|
40
|
+
})
|
|
41
|
+
declareSchedule(cfg, {
|
|
42
|
+
id: 'app-purge-expired', queue: APP_MAINTENANCE, name: 'app:maintenance:purge', every: 15 * 60_000,
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
And only in the process that runs them: `listenQueues(cfg, APP_MAINTENANCE)` plus a processor per
|
|
47
|
+
job name, registered while the context is wired.
|
|
48
|
+
|
|
49
|
+
- **`pattern` for the calendar, `every` for a frequency.** A nightly job is a pattern with an
|
|
50
|
+
explicit `tz`; "every quarter hour, whenever" is `every`. Pick an odd minute (`17 3 * * *`) so
|
|
51
|
+
many applications' sweeps do not stampede one Redis at the top of the hour.
|
|
52
|
+
- **`every` runs at once** when the scheduler is created (unless `startDate` says otherwise); a
|
|
53
|
+
pattern waits for its next match unless `immediately: true`, which fires only when the scheduler
|
|
54
|
+
is created or its declaration changes — never on an unchanged restart.
|
|
55
|
+
- **The id is permanent.** It is the scheduler's identity in the broker: any other field changes in
|
|
56
|
+
place, a renamed id is a removed schedule plus a new one. Prefix it with the application
|
|
57
|
+
(`app-…`) — ids share one namespace per queue.
|
|
58
|
+
- **Declaration errors surface at boot.** `declareSchedule` throws `UnknownQueue`,
|
|
59
|
+
`UnknownJobName` or `ScheduleMisdeclared` (`<id>:<reason>`) rather than letting the broker fail
|
|
60
|
+
on every tick.
|
|
61
|
+
- **`opts` sets retries and retention for every run; `id` and `delay` are refused** — the broker
|
|
62
|
+
names each run and places it on the schedule.
|
|
63
|
+
|
|
64
|
+
## Writing the processor
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const log = logger('maintenance') // from '@owlmeans/log'
|
|
68
|
+
|
|
69
|
+
worker.process<Record<string, never>, SweepReport>(APP_MAINTENANCE, 'app:maintenance:reconcile',
|
|
70
|
+
async job => {
|
|
71
|
+
const report = { scanned: 0, repaired: 0, failed: 0 }
|
|
72
|
+
for await (const page of organizations({ size: 200 })) {
|
|
73
|
+
await job.touch()
|
|
74
|
+
for (const organization of page) {
|
|
75
|
+
try {
|
|
76
|
+
report.repaired += await reconcile(organization.entityId) ? 1 : 0
|
|
77
|
+
} catch (error) {
|
|
78
|
+
report.failed++
|
|
79
|
+
log.error('Reconcile failed', { entityId: organization.entityId, error })
|
|
80
|
+
}
|
|
81
|
+
report.scanned++
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
log.info('Maintenance run finished', { scheduled: job.scheduled, ...report }, { event: 'job.stop' })
|
|
85
|
+
return report
|
|
86
|
+
})
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
- **A scheduled run has no caller.** No credentials, no entity, no request: it is a processor job,
|
|
90
|
+
never a guarded entrypoint. A step that must go through another service's guard calls that
|
|
91
|
+
service with service credentials.
|
|
92
|
+
- **Idempotent per item, not per run.** A worker rolled out mid-sweep, a stalled lock or a manual
|
|
93
|
+
re-run repeats the whole sweep; each item's repair must be a no-op the second time.
|
|
94
|
+
- **One item's failure is logged and counted, never thrown.** A thrown sweep is retried from the
|
|
95
|
+
start, or dropped after its attempts — either way the other items pay for one bad record.
|
|
96
|
+
- **`touch()` per page.** A sweep over every organization outlives `lockDuration` easily; silence
|
|
97
|
+
hands the job to another worker while this one is still going.
|
|
98
|
+
- **Return a small report.** It lands on the completed job, where an operator reads it.
|
|
99
|
+
|
|
100
|
+
## Overlap, replicas and deploys
|
|
101
|
+
|
|
102
|
+
- **One job per tick, whatever the replica count.** The broker produces one job; one worker takes
|
|
103
|
+
it. Several replicas listening to the queue do not multiply runs.
|
|
104
|
+
- **Runs can overlap on a concurrent queue.** The next run is produced when the previous one
|
|
105
|
+
starts, so a run that outlasts the interval meets its successor. Put sweeps on their own queue
|
|
106
|
+
with `concurrency: 1`, apart from interactive lanes.
|
|
107
|
+
- **A schedule needs a consumer.** Only a listening worker creates the scheduler, and the next run
|
|
108
|
+
is produced only when the previous one starts processing. A queue nothing consumes stops.
|
|
109
|
+
- **Every listener reconciles at start, from its own configuration.** It creates or updates what it
|
|
110
|
+
declares and removes the schedules it owns (`owlmeans:` scheduler ids) that it does not. Every
|
|
111
|
+
process listening to one queue must load the same schedule list; during a rolling deploy the
|
|
112
|
+
newest process to start wins, and the old pods leave the broker alone after their own start.
|
|
113
|
+
- **Removing a schedule is deleting its declaration.** The next worker start removes the scheduler.
|
|
114
|
+
So is a declaration whose job name the queue no longer accepts, or whose `endDate` has passed.
|
|
115
|
+
- **Scheduling never costs consumption.** A refused declaration or a broker failure while
|
|
116
|
+
reconciling is logged and skipped; the worker keeps consuming. Look for
|
|
117
|
+
`redis-queue-schedules:<queue>` in the worker's log when a schedule does not appear.
|
|
118
|
+
|
|
119
|
+
## Diagnosing "it never ran"
|
|
120
|
+
|
|
121
|
+
1. Is some process listening to the queue (`listenQueues`) and is its worker up?
|
|
122
|
+
2. Did that process's start log a `redis-queue-schedules:<queue>` refusal?
|
|
123
|
+
3. Does `new Queue(queue, { connection, prefix }).getJobSchedulers()` list `owlmeans:<id>` with the
|
|
124
|
+
expected `pattern`/`every`, `tz` and `next`?
|
|
125
|
+
4. Is a processor registered for the job name? A run without one fails once as `UnknownJobName`
|
|
126
|
+
and shows in the failed state.
|
|
127
|
+
5. Is a previous run still active on a `concurrency: 1` queue?
|
|
128
|
+
|
|
129
|
+
## Testing
|
|
130
|
+
|
|
131
|
+
- **The declaration** is category A in the application's own shared package: build the config,
|
|
132
|
+
`assertSchedules(cfg)`, and pin ids and job names against the queue declaration.
|
|
133
|
+
- **The processor** is tested as a function over a fake `JobContext` or a real context — it is
|
|
134
|
+
ordinary code with a `touch`.
|
|
135
|
+
- **Against a broker** (Redis-gated): the worker's Ready-stage start is not awaited by
|
|
136
|
+
`context.init()`, so poll the broker (`getJobSchedulers`) or wait for the first run instead of
|
|
137
|
+
asserting straight after boot. A queue's schedulers go with `obliterate()`.
|
|
138
|
+
|
|
139
|
+
## External docs
|
|
140
|
+
|
|
141
|
+
- https://docs.bullmq.io/guide/job-schedulers — `upsertJobScheduler(id, { every | pattern, tz,
|
|
142
|
+
startDate, endDate, limit, immediately }, { name, data, opts })` creates or updates one scheduler
|
|
143
|
+
per id and replaces its pending run; `getJobSchedulers()` / `removeJobScheduler(id)`. The next job
|
|
144
|
+
is added when the previous one starts processing, so a worker must be consuming. Produced jobs
|
|
145
|
+
carry `repeatJobKey` = the scheduler id.
|
|
146
|
+
|
|
147
|
+
## Related
|
|
148
|
+
|
|
149
|
+
- `queue` — `declareSchedule`, `JobContext.scheduled`, processor rules
|
|
150
|
+
- `redis-queue` — `syncSchedules`, the `owlmeans:` ownership prefix, the reconciliation rules
|
|
151
|
+
- `resource-choice` — whether recurring work belongs on a queue at all
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { AbstractRequest } from '@owlmeans/entrypoint';
|
|
2
|
+
import type { BasicContext } from '@owlmeans/context';
|
|
3
|
+
import type { Config, Context, JobContext, JobEnvelope, JobReply, QueueJobMeta } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Rebuild the request the producer described. A queued call is still a call: the same guards, the
|
|
6
|
+
* same filter, the same handler run against it — only the wire is different.
|
|
7
|
+
*/
|
|
8
|
+
export declare const requestOf: (envelope: JobEnvelope, path: string, context?: BasicContext<any>, job?: QueueJobMeta) => AbstractRequest;
|
|
9
|
+
/** Read broker identity only where an entrypoint truly needs to bind work to an admission claim. */
|
|
10
|
+
export declare const queueJobOf: (request: unknown) => QueueJobMeta | null;
|
|
11
|
+
/**
|
|
12
|
+
* Freshness is judged from when the job was ENQUEUED, not from now.
|
|
13
|
+
*
|
|
14
|
+
* A signed envelope proves who produced it, and a replay window keeps a captured one from being
|
|
15
|
+
* useful forever. But a job can legitimately sit behind a long backlog, and judging it on pickup
|
|
16
|
+
* would reject exactly the work that a busy queue delayed — so the producer's timestamp is what
|
|
17
|
+
* the window applies to.
|
|
18
|
+
*
|
|
19
|
+
* @throws {EnvelopeExpired}
|
|
20
|
+
*/
|
|
21
|
+
export declare const assertFresh: (envelope: JobEnvelope, ttl?: number) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Run one queued entrypoint call and describe the outcome.
|
|
24
|
+
*
|
|
25
|
+
* It never throws for a DOMAIN failure — the error is marshalled into the returned reply so the
|
|
26
|
+
* producer can rebuild it as its own class, and so the broker does not count a legitimate refusal
|
|
27
|
+
* as a job to retry. Infrastructure failures are left to propagate: those are what retries are for.
|
|
28
|
+
*/
|
|
29
|
+
export declare const handleJob: <C extends Config, T extends Context<C>>(context: T, job: JobContext<JobEnvelope>) => Promise<JobReply>;
|
|
30
|
+
//# sourceMappingURL=bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAkC,MAAM,sBAAsB,CAAA;AAC3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAMrD,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAGlG;;;GAGG;AACH,eAAO,MAAM,SAAS,aACV,WAAW,QAAQ,MAAM,YAAY,YAAY,CAAC,GAAG,CAAC,QAAQ,YAAY,KACnF,eAWD,CAAA;AAEF,oGAAoG;AACpG,eAAO,MAAM,UAAU,YAAa,OAAO,KAAG,YAAY,GAAG,IAK5D,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,aAAc,WAAW,QAAQ,MAAM,KAAG,IAQjE,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GAAU,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,WAC3D,CAAC,OAAO,UAAU,CAAC,WAAW,CAAC,KACvC,OAAO,CAAC,QAAQ,CA2DlB,CAAA"}
|
package/build/bridge.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { EntrypointOutcome, provideResponse } from '@owlmeans/entrypoint';
|
|
2
|
+
import { AuthorizationError } from '@owlmeans/auth';
|
|
3
|
+
import { attachEntity } from '@owlmeans/auth-common';
|
|
4
|
+
import { ResilientError } from '@owlmeans/error';
|
|
5
|
+
import { EnvelopeExpired, JobNotServed } from './errors.js';
|
|
6
|
+
/**
|
|
7
|
+
* Rebuild the request the producer described. A queued call is still a call: the same guards, the
|
|
8
|
+
* same filter, the same handler run against it — only the wire is different.
|
|
9
|
+
*/
|
|
10
|
+
export const requestOf = (envelope, path, context, job) => ({
|
|
11
|
+
alias: envelope.alias,
|
|
12
|
+
params: (envelope.params ?? {}),
|
|
13
|
+
body: envelope.body,
|
|
14
|
+
headers: (envelope.headers ?? {}),
|
|
15
|
+
query: (envelope.query ?? {}),
|
|
16
|
+
path,
|
|
17
|
+
// Handlers reach their context through `original._ctx`, which the HTTP boundary sets on the raw
|
|
18
|
+
// Fastify request. There is no raw request here, so the shape is supplied deliberately — a
|
|
19
|
+
// handler must not have to know which transport delivered it.
|
|
20
|
+
original: context != null || job != null ? { _ctx: context, _job: job } : undefined,
|
|
21
|
+
});
|
|
22
|
+
/** Read broker identity only where an entrypoint truly needs to bind work to an admission claim. */
|
|
23
|
+
export const queueJobOf = (request) => {
|
|
24
|
+
if (request == null || typeof request !== 'object' || !('original' in request))
|
|
25
|
+
return null;
|
|
26
|
+
const original = request.original;
|
|
27
|
+
if (original == null || typeof original !== 'object' || !('_job' in original))
|
|
28
|
+
return null;
|
|
29
|
+
return original._job ?? null;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Freshness is judged from when the job was ENQUEUED, not from now.
|
|
33
|
+
*
|
|
34
|
+
* A signed envelope proves who produced it, and a replay window keeps a captured one from being
|
|
35
|
+
* useful forever. But a job can legitimately sit behind a long backlog, and judging it on pickup
|
|
36
|
+
* would reject exactly the work that a busy queue delayed — so the producer's timestamp is what
|
|
37
|
+
* the window applies to.
|
|
38
|
+
*
|
|
39
|
+
* @throws {EnvelopeExpired}
|
|
40
|
+
*/
|
|
41
|
+
export const assertFresh = (envelope, ttl) => {
|
|
42
|
+
if (ttl == null || envelope.enqueuedAt == null) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const age = (Date.now() - new Date(envelope.enqueuedAt).getTime()) / 1000;
|
|
46
|
+
if (age > ttl) {
|
|
47
|
+
throw new EnvelopeExpired(`${envelope.alias}: ${Math.round(age)}s > ${ttl}s`);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Run one queued entrypoint call and describe the outcome.
|
|
52
|
+
*
|
|
53
|
+
* It never throws for a DOMAIN failure — the error is marshalled into the returned reply so the
|
|
54
|
+
* producer can rebuild it as its own class, and so the broker does not count a legitimate refusal
|
|
55
|
+
* as a job to retry. Infrastructure failures are left to propagate: those are what retries are for.
|
|
56
|
+
*/
|
|
57
|
+
export const handleJob = async (context, job) => {
|
|
58
|
+
const envelope = job.data;
|
|
59
|
+
try {
|
|
60
|
+
assertFresh(envelope, context.cfg.queue?.envelopeTtl);
|
|
61
|
+
const entrypoint = context.entrypoint(envelope.alias);
|
|
62
|
+
if (entrypoint.handle == null) {
|
|
63
|
+
throw new JobNotServed(envelope.alias);
|
|
64
|
+
}
|
|
65
|
+
const request = requestOf(envelope, entrypoint.path(), context, {
|
|
66
|
+
id: job.id, name: job.name, queue: job.queue, attempt: job.attempt, touch: job.touch,
|
|
67
|
+
});
|
|
68
|
+
const response = provideResponse();
|
|
69
|
+
const guards = entrypoint.getGuards();
|
|
70
|
+
if (guards.length > 0) {
|
|
71
|
+
let matched;
|
|
72
|
+
for (const alias of guards) {
|
|
73
|
+
const guard = context.service(alias);
|
|
74
|
+
if (await guard.match(request, response)) {
|
|
75
|
+
matched = guard;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (matched == null) {
|
|
80
|
+
throw new AuthorizationError(`queue:${envelope.alias}`);
|
|
81
|
+
}
|
|
82
|
+
const auth = provideResponse();
|
|
83
|
+
if (!await matched.handle(request, auth)) {
|
|
84
|
+
throw new AuthorizationError(`queue:${envelope.alias}:${matched.alias}`);
|
|
85
|
+
}
|
|
86
|
+
request.auth = auth.value;
|
|
87
|
+
const entity = await attachEntity(context, request);
|
|
88
|
+
if (entity != null) {
|
|
89
|
+
request.entity = entity;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
await entrypoint.handle(request, response);
|
|
93
|
+
if (response.error != null) {
|
|
94
|
+
return { error: ResilientError.marshal(response.error).message };
|
|
95
|
+
}
|
|
96
|
+
return { value: response.value, outcome: response.outcome ?? EntrypointOutcome.Ok };
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
// A refusal the caller must see as its own class — `ContentRefused`, `AgentLocked` — travels
|
|
100
|
+
// in the reply. Only a broker- or connection-level fault should ever reach the retry logic:
|
|
101
|
+
// retrying a refusal just spends the work again to be refused identically.
|
|
102
|
+
if (e instanceof ResilientError) {
|
|
103
|
+
return { error: ResilientError.marshal(e).message };
|
|
104
|
+
}
|
|
105
|
+
throw e;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Config, JobOptions, QueueDeclaration, QueueWorkerOptions, ScheduleDeclaration } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Add a queue to the shared configuration. Every process in the monorepo loads the same
|
|
4
|
+
* declarations — a producer needs them to know a queue exists and what it accepts, a worker needs
|
|
5
|
+
* them to bind. Declaring twice replaces, so a helper that runs per app is safe to call.
|
|
6
|
+
*/
|
|
7
|
+
export declare const declareQueue: <C extends Config>(cfg: C, name: string, jobs: string[], opts?: {
|
|
8
|
+
worker?: QueueWorkerOptions;
|
|
9
|
+
defaults?: JobOptions;
|
|
10
|
+
}) => C;
|
|
11
|
+
/**
|
|
12
|
+
* Name the queues this process consumes. It is what turns an otherwise identical binary into a
|
|
13
|
+
* worker, which is why it lives in the process's own config and never in a declaration.
|
|
14
|
+
*/
|
|
15
|
+
export declare const listenQueues: <C extends Config>(cfg: C, ...names: string[]) => C;
|
|
16
|
+
/**
|
|
17
|
+
* @throws {UnknownQueue}
|
|
18
|
+
*/
|
|
19
|
+
export declare const queueOf: <C extends Config>(cfg: C, name: string) => QueueDeclaration;
|
|
20
|
+
export declare const queueOfJob: <C extends Config>(cfg: C, job: string) => QueueDeclaration | undefined;
|
|
21
|
+
export declare const isListening: <C extends Config>(cfg: C, name: string) => boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Whether the broker can carry a schedule out as written. Nothing is recorded or changed.
|
|
24
|
+
*
|
|
25
|
+
* @throws {ScheduleMisdeclared} naming the schedule id and the reason.
|
|
26
|
+
* @throws {UnknownQueue} when the schedule's queue is not declared.
|
|
27
|
+
* @throws {UnknownJobName} when that queue does not accept the schedule's job name — a scheduled
|
|
28
|
+
* run of a name nothing declares would fail on every tick instead of once, at declaration.
|
|
29
|
+
*/
|
|
30
|
+
export declare const assertSchedule: <C extends Config>(cfg: C, schedule: ScheduleDeclaration) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Add a recurring job to the shared configuration. Declare the queue first — a schedule is checked
|
|
33
|
+
* against it here. Declaring an id twice replaces, like `declareQueue`.
|
|
34
|
+
*
|
|
35
|
+
* Declaring is all this does: the driver creates, updates and removes the broker's schedulers when
|
|
36
|
+
* a worker that listens to the queue starts.
|
|
37
|
+
*
|
|
38
|
+
* @throws {ScheduleMisdeclared} / {UnknownQueue} / {UnknownJobName} — see `assertSchedule`.
|
|
39
|
+
*/
|
|
40
|
+
export declare const declareSchedule: <C extends Config>(cfg: C, schedule: ScheduleDeclaration) => C;
|
|
41
|
+
/** The declared schedules, of one queue when it is named. */
|
|
42
|
+
export declare const schedulesOf: <C extends Config>(cfg: C, queue?: string) => ScheduleDeclaration[];
|
|
43
|
+
/**
|
|
44
|
+
* Check every declared schedule, including any written into the configuration without
|
|
45
|
+
* `declareSchedule`, and refuse two under one id.
|
|
46
|
+
*
|
|
47
|
+
* @throws {ScheduleMisdeclared} / {UnknownQueue} / {UnknownJobName} for the first one that fails.
|
|
48
|
+
*/
|
|
49
|
+
export declare const assertSchedules: <C extends Config>(cfg: C) => void;
|
|
50
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,EAC9E,MAAM,YAAY,CAAA;AAGnB;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,MAAM,OACtC,CAAC,QAAQ,MAAM,QAAQ,MAAM,EAAE,SAAS;IAAE,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,EAAE,UAAU,CAAA;CAAE,KAClG,CAcF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,MAAM,OAAO,CAAC,YAAY,MAAM,EAAE,KAAG,CAM3E,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,OAAO,GAAI,CAAC,SAAS,MAAM,OAAO,CAAC,QAAQ,MAAM,KAAG,gBAQhE,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,MAAM,OAAO,CAAC,OAAO,MAAM,KAAG,gBAAgB,GAAG,SACpB,CAAA;AAElE,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,MAAM,OAAO,CAAC,QAAQ,MAAM,KAAG,OACzB,CAAA;AAM5C;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,MAAM,OAAO,CAAC,YAAY,mBAAmB,KAAG,IAoDxF,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,MAAM,OAAO,CAAC,YAAY,mBAAmB,KAAG,CAezF,CAAA;AAED,6DAA6D;AAC7D,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,MAAM,OAAO,CAAC,UAAU,MAAM,KAAG,mBAAmB,EACE,CAAA;AAE5F;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,MAAM,OAAO,CAAC,KAAG,IAS1D,CAAA"}
|
package/build/config.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { ScheduleMisdeclared, UnknownJobName, UnknownQueue } from './errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Add a queue to the shared configuration. Every process in the monorepo loads the same
|
|
4
|
+
* declarations — a producer needs them to know a queue exists and what it accepts, a worker needs
|
|
5
|
+
* them to bind. Declaring twice replaces, so a helper that runs per app is safe to call.
|
|
6
|
+
*/
|
|
7
|
+
export const declareQueue = (cfg, name, jobs, opts) => {
|
|
8
|
+
const queue = { name, jobs, ...opts };
|
|
9
|
+
const queues = cfg.queue?.queues ?? [];
|
|
10
|
+
const existing = queues.findIndex(declared => declared.name === name);
|
|
11
|
+
if (existing < 0) {
|
|
12
|
+
queues.push(queue);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
queues[existing] = queue;
|
|
16
|
+
}
|
|
17
|
+
cfg.queue = { ...cfg.queue, queues };
|
|
18
|
+
return cfg;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Name the queues this process consumes. It is what turns an otherwise identical binary into a
|
|
22
|
+
* worker, which is why it lives in the process's own config and never in a declaration.
|
|
23
|
+
*/
|
|
24
|
+
export const listenQueues = (cfg, ...names) => {
|
|
25
|
+
const listen = new Set([...(cfg.queue?.listen ?? []), ...names]);
|
|
26
|
+
cfg.queue = { ...cfg.queue, listen: [...listen] };
|
|
27
|
+
return cfg;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* @throws {UnknownQueue}
|
|
31
|
+
*/
|
|
32
|
+
export const queueOf = (cfg, name) => {
|
|
33
|
+
const queue = cfg.queue?.queues?.find(declared => declared.name === name);
|
|
34
|
+
if (queue == null) {
|
|
35
|
+
throw new UnknownQueue(name);
|
|
36
|
+
}
|
|
37
|
+
return queue;
|
|
38
|
+
};
|
|
39
|
+
export const queueOfJob = (cfg, job) => cfg.queue?.queues?.find(declared => declared.jobs.includes(job));
|
|
40
|
+
export const isListening = (cfg, name) => cfg.queue?.listen?.includes(name) === true;
|
|
41
|
+
/** A date option the broker can read — a `Date`, epoch milliseconds or a parsable string. */
|
|
42
|
+
const isInstant = (value) => Number.isFinite((value instanceof Date ? value : new Date(value)).getTime());
|
|
43
|
+
/**
|
|
44
|
+
* Whether the broker can carry a schedule out as written. Nothing is recorded or changed.
|
|
45
|
+
*
|
|
46
|
+
* @throws {ScheduleMisdeclared} naming the schedule id and the reason.
|
|
47
|
+
* @throws {UnknownQueue} when the schedule's queue is not declared.
|
|
48
|
+
* @throws {UnknownJobName} when that queue does not accept the schedule's job name — a scheduled
|
|
49
|
+
* run of a name nothing declares would fail on every tick instead of once, at declaration.
|
|
50
|
+
*/
|
|
51
|
+
export const assertSchedule = (cfg, schedule) => {
|
|
52
|
+
const { id } = schedule;
|
|
53
|
+
if (typeof id !== 'string' || id.trim() === '') {
|
|
54
|
+
throw new ScheduleMisdeclared('(empty):id');
|
|
55
|
+
}
|
|
56
|
+
const queue = queueOf(cfg, schedule.queue);
|
|
57
|
+
if (!queue.jobs.includes(schedule.name)) {
|
|
58
|
+
throw new UnknownJobName(`${schedule.queue}:${schedule.name}`);
|
|
59
|
+
}
|
|
60
|
+
const every = schedule.every != null;
|
|
61
|
+
const pattern = schedule.pattern != null;
|
|
62
|
+
if (every === pattern) {
|
|
63
|
+
throw new ScheduleMisdeclared(`${id}:every-or-pattern`);
|
|
64
|
+
}
|
|
65
|
+
if (every && !(Number.isSafeInteger(schedule.every) && schedule.every > 0)) {
|
|
66
|
+
throw new ScheduleMisdeclared(`${id}:every`);
|
|
67
|
+
}
|
|
68
|
+
if (pattern && (typeof schedule.pattern !== 'string' || schedule.pattern.trim() === '')) {
|
|
69
|
+
throw new ScheduleMisdeclared(`${id}:pattern`);
|
|
70
|
+
}
|
|
71
|
+
// Both only mean something to a cron pattern: an interval has no wall clock to read in a time
|
|
72
|
+
// zone, and its first run is immediate already.
|
|
73
|
+
if (!pattern && schedule.tz != null) {
|
|
74
|
+
throw new ScheduleMisdeclared(`${id}:tz`);
|
|
75
|
+
}
|
|
76
|
+
if (!pattern && schedule.immediately === true) {
|
|
77
|
+
throw new ScheduleMisdeclared(`${id}:immediately`);
|
|
78
|
+
}
|
|
79
|
+
if (schedule.immediately === true && schedule.startDate != null) {
|
|
80
|
+
throw new ScheduleMisdeclared(`${id}:immediately-start-date`);
|
|
81
|
+
}
|
|
82
|
+
if (schedule.limit != null && !(Number.isSafeInteger(schedule.limit) && schedule.limit > 0)) {
|
|
83
|
+
throw new ScheduleMisdeclared(`${id}:limit`);
|
|
84
|
+
}
|
|
85
|
+
if (schedule.startDate != null && !isInstant(schedule.startDate)) {
|
|
86
|
+
throw new ScheduleMisdeclared(`${id}:start-date`);
|
|
87
|
+
}
|
|
88
|
+
if (schedule.endDate != null && !isInstant(schedule.endDate)) {
|
|
89
|
+
throw new ScheduleMisdeclared(`${id}:end-date`);
|
|
90
|
+
}
|
|
91
|
+
// The type already omits both; a declaration assembled at runtime still reaches this check. The
|
|
92
|
+
// broker names every run itself and places it on the schedule, so either would be overridden.
|
|
93
|
+
const opts = schedule.opts;
|
|
94
|
+
if (opts?.id != null) {
|
|
95
|
+
throw new ScheduleMisdeclared(`${id}:opts-id`);
|
|
96
|
+
}
|
|
97
|
+
if (opts?.delay != null) {
|
|
98
|
+
throw new ScheduleMisdeclared(`${id}:opts-delay`);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Add a recurring job to the shared configuration. Declare the queue first — a schedule is checked
|
|
103
|
+
* against it here. Declaring an id twice replaces, like `declareQueue`.
|
|
104
|
+
*
|
|
105
|
+
* Declaring is all this does: the driver creates, updates and removes the broker's schedulers when
|
|
106
|
+
* a worker that listens to the queue starts.
|
|
107
|
+
*
|
|
108
|
+
* @throws {ScheduleMisdeclared} / {UnknownQueue} / {UnknownJobName} — see `assertSchedule`.
|
|
109
|
+
*/
|
|
110
|
+
export const declareSchedule = (cfg, schedule) => {
|
|
111
|
+
assertSchedule(cfg, schedule);
|
|
112
|
+
const schedules = cfg.queue?.schedules ?? [];
|
|
113
|
+
const existing = schedules.findIndex(declared => declared.id === schedule.id);
|
|
114
|
+
if (existing < 0) {
|
|
115
|
+
schedules.push(schedule);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
schedules[existing] = schedule;
|
|
119
|
+
}
|
|
120
|
+
cfg.queue = { ...cfg.queue, schedules };
|
|
121
|
+
return cfg;
|
|
122
|
+
};
|
|
123
|
+
/** The declared schedules, of one queue when it is named. */
|
|
124
|
+
export const schedulesOf = (cfg, queue) => (cfg.queue?.schedules ?? []).filter(schedule => queue == null || schedule.queue === queue);
|
|
125
|
+
/**
|
|
126
|
+
* Check every declared schedule, including any written into the configuration without
|
|
127
|
+
* `declareSchedule`, and refuse two under one id.
|
|
128
|
+
*
|
|
129
|
+
* @throws {ScheduleMisdeclared} / {UnknownQueue} / {UnknownJobName} for the first one that fails.
|
|
130
|
+
*/
|
|
131
|
+
export const assertSchedules = (cfg) => {
|
|
132
|
+
const seen = new Set();
|
|
133
|
+
for (const schedule of schedulesOf(cfg)) {
|
|
134
|
+
assertSchedule(cfg, schedule);
|
|
135
|
+
if (seen.has(schedule.id)) {
|
|
136
|
+
throw new ScheduleMisdeclared(`${schedule.id}:duplicate`);
|
|
137
|
+
}
|
|
138
|
+
seen.add(schedule.id);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare const DEFAULT_ALIAS = "queue";
|
|
2
|
+
/**
|
|
3
|
+
* The state a job is in, as the broker reports it. `Waiting` covers both a job queued normally
|
|
4
|
+
* and one held by an unfinished parent — the difference matters to the broker, never to a caller
|
|
5
|
+
* asking whether an answer has arrived.
|
|
6
|
+
*/
|
|
7
|
+
export declare enum JobState {
|
|
8
|
+
Waiting = "waiting",
|
|
9
|
+
Delayed = "delayed",
|
|
10
|
+
Active = "active",
|
|
11
|
+
Completed = "completed",
|
|
12
|
+
Failed = "failed",
|
|
13
|
+
Unknown = "unknown"
|
|
14
|
+
}
|
|
15
|
+
export declare enum JobEventType {
|
|
16
|
+
Completed = "completed",
|
|
17
|
+
Failed = "failed",
|
|
18
|
+
Progress = "progress"
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* How long a caller waits for a reply when neither the route nor the request says. Long enough
|
|
22
|
+
* for work that talks to a model, short enough that a lost job surfaces as an error rather than a
|
|
23
|
+
* hung request.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DEFAULT_JOB_TIMEOUT = 60000;
|
|
26
|
+
/**
|
|
27
|
+
* Retries default to one attempt: the jobs here are mostly LLM work, and a blind retry re-spends
|
|
28
|
+
* the tokens that just failed. A queue whose jobs are cheap and idempotent raises it per queue.
|
|
29
|
+
*/
|
|
30
|
+
export declare const DEFAULT_ATTEMPTS = 1;
|
|
31
|
+
/** The transport identifier owned by the queue package. */
|
|
32
|
+
export declare const QUEUE_PROTOCOL: 'queue';
|
|
33
|
+
//# sourceMappingURL=consts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,aAAa,UAAU,CAAA;AAEpC;;;;GAIG;AACH,oBAAY,QAAQ;IAClB,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,SAAS,cAAc;IACvB,MAAM,WAAW;IACjB,OAAO,YAAY;CACpB;AAED,oBAAY,YAAY;IACtB,SAAS,cAAc;IACvB,MAAM,WAAW;IACjB,QAAQ,aAAa;CACtB;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,QAAS,CAAA;AAEzC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,IAAI,CAAA;AAEjC,2DAA2D;AAC3D,eAAO,MAAM,cAAc,EAAG,OAAgB,CAAA"}
|
package/build/consts.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export const DEFAULT_ALIAS = 'queue';
|
|
2
|
+
/**
|
|
3
|
+
* The state a job is in, as the broker reports it. `Waiting` covers both a job queued normally
|
|
4
|
+
* and one held by an unfinished parent — the difference matters to the broker, never to a caller
|
|
5
|
+
* asking whether an answer has arrived.
|
|
6
|
+
*/
|
|
7
|
+
export var JobState;
|
|
8
|
+
(function (JobState) {
|
|
9
|
+
JobState["Waiting"] = "waiting";
|
|
10
|
+
JobState["Delayed"] = "delayed";
|
|
11
|
+
JobState["Active"] = "active";
|
|
12
|
+
JobState["Completed"] = "completed";
|
|
13
|
+
JobState["Failed"] = "failed";
|
|
14
|
+
JobState["Unknown"] = "unknown";
|
|
15
|
+
})(JobState || (JobState = {}));
|
|
16
|
+
export var JobEventType;
|
|
17
|
+
(function (JobEventType) {
|
|
18
|
+
JobEventType["Completed"] = "completed";
|
|
19
|
+
JobEventType["Failed"] = "failed";
|
|
20
|
+
JobEventType["Progress"] = "progress";
|
|
21
|
+
})(JobEventType || (JobEventType = {}));
|
|
22
|
+
/**
|
|
23
|
+
* How long a caller waits for a reply when neither the route nor the request says. Long enough
|
|
24
|
+
* for work that talks to a model, short enough that a lost job surfaces as an error rather than a
|
|
25
|
+
* hung request.
|
|
26
|
+
*/
|
|
27
|
+
export const DEFAULT_JOB_TIMEOUT = 60_000;
|
|
28
|
+
/**
|
|
29
|
+
* Retries default to one attempt: the jobs here are mostly LLM work, and a blind retry re-spends
|
|
30
|
+
* the tokens that just failed. A queue whose jobs are cheap and idempotent raises it per queue.
|
|
31
|
+
*/
|
|
32
|
+
export const DEFAULT_ATTEMPTS = 1;
|
|
33
|
+
/** The transport identifier owned by the queue package. */
|
|
34
|
+
export const QUEUE_PROTOCOL = 'queue';
|
|
35
|
+
//# sourceMappingURL=consts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAA;AAEpC;;;;GAIG;AACH,MAAM,CAAN,IAAY,QAOX;AAPD,WAAY,QAAQ;IAClB,+BAAmB,CAAA;IACnB,+BAAmB,CAAA;IACnB,6BAAiB,CAAA;IACjB,mCAAuB,CAAA;IACvB,6BAAiB,CAAA;IACjB,+BAAmB,CAAA;AACrB,CAAC,EAPW,QAAQ,KAAR,QAAQ,QAOnB;AAED,MAAM,CAAN,IAAY,YAIX;AAJD,WAAY,YAAY;IACtB,uCAAuB,CAAA;IACvB,iCAAiB,CAAA;IACjB,qCAAqB,CAAA;AACvB,CAAC,EAJW,YAAY,KAAZ,YAAY,QAIvB;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAA;AAEzC;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAA;AAEjC,2DAA2D;AAC3D,MAAM,CAAC,MAAM,cAAc,GAAG,OAAgB,CAAA"}
|