@ddd-ts-kit/scheduling 0.10.0 → 0.11.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/README.md +73 -7
- package/dist/index.d.ts +25 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/job-runner.d.ts.map +1 -1
- package/dist/job-runner.js +1 -13
- package/dist/job-runner.js.map +1 -1
- package/dist/metric-names.d.ts +2 -0
- package/dist/metric-names.d.ts.map +1 -1
- package/dist/metric-names.js +2 -0
- package/dist/metric-names.js.map +1 -1
- package/dist/process/no-timeout-job-error.d.ts +6 -0
- package/dist/process/no-timeout-job-error.d.ts.map +1 -0
- package/dist/process/no-timeout-job-error.js +9 -0
- package/dist/process/no-timeout-job-error.js.map +1 -0
- package/dist/process/stored-process-runner.d.ts +24 -0
- package/dist/process/stored-process-runner.d.ts.map +1 -0
- package/dist/process/stored-process-runner.js +89 -0
- package/dist/process/stored-process-runner.js.map +1 -0
- package/dist/queue/background-job-definition.d.ts +9 -0
- package/dist/queue/background-job-definition.d.ts.map +1 -0
- package/dist/queue/background-job-definition.js +2 -0
- package/dist/queue/background-job-definition.js.map +1 -0
- package/dist/queue/background-job-observer.d.ts +4 -0
- package/dist/queue/background-job-observer.d.ts.map +1 -0
- package/dist/queue/background-job-observer.js +2 -0
- package/dist/queue/background-job-observer.js.map +1 -0
- package/dist/queue/background-job-outcome.d.ts +9 -0
- package/dist/queue/background-job-outcome.d.ts.map +1 -0
- package/dist/queue/background-job-outcome.js +2 -0
- package/dist/queue/background-job-outcome.js.map +1 -0
- package/dist/queue/background-job-recorder.d.ts +19 -0
- package/dist/queue/background-job-recorder.d.ts.map +1 -0
- package/dist/queue/background-job-recorder.js +87 -0
- package/dist/queue/background-job-recorder.js.map +1 -0
- package/dist/queue/background-job-run.d.ts +15 -0
- package/dist/queue/background-job-run.d.ts.map +1 -0
- package/dist/queue/background-job-run.js +2 -0
- package/dist/queue/background-job-run.js.map +1 -0
- package/dist/queue/claimed-job-runner.d.ts +44 -0
- package/dist/queue/claimed-job-runner.d.ts.map +1 -0
- package/dist/queue/claimed-job-runner.js +178 -0
- package/dist/queue/claimed-job-runner.js.map +1 -0
- package/dist/queue/errors/attempts-exhausted-error.d.ts +6 -0
- package/dist/queue/errors/attempts-exhausted-error.d.ts.map +1 -0
- package/dist/queue/errors/attempts-exhausted-error.js +9 -0
- package/dist/queue/errors/attempts-exhausted-error.js.map +1 -0
- package/dist/queue/errors/invalid-enqueue-error.d.ts +8 -0
- package/dist/queue/errors/invalid-enqueue-error.d.ts.map +1 -0
- package/dist/queue/errors/invalid-enqueue-error.js +15 -0
- package/dist/queue/errors/invalid-enqueue-error.js.map +1 -0
- package/dist/queue/errors/job-interrupted-error.d.ts +6 -0
- package/dist/queue/errors/job-interrupted-error.d.ts.map +1 -0
- package/dist/queue/errors/job-interrupted-error.js +9 -0
- package/dist/queue/errors/job-interrupted-error.js.map +1 -0
- package/dist/queue/errors/unknown-background-job-error.d.ts +6 -0
- package/dist/queue/errors/unknown-background-job-error.d.ts.map +1 -0
- package/dist/queue/errors/unknown-background-job-error.js +9 -0
- package/dist/queue/errors/unknown-background-job-error.js.map +1 -0
- package/dist/queue/queue-state.d.ts +12 -0
- package/dist/queue/queue-state.d.ts.map +1 -0
- package/dist/queue/queue-state.js +2 -0
- package/dist/queue/queue-state.js.map +1 -0
- package/dist/queue/queue-worker-options.d.ts +29 -0
- package/dist/queue/queue-worker-options.d.ts.map +1 -0
- package/dist/queue/queue-worker-options.js +2 -0
- package/dist/queue/queue-worker-options.js.map +1 -0
- package/dist/queue/queue-worker.d.ts +52 -0
- package/dist/queue/queue-worker.d.ts.map +1 -0
- package/dist/queue/queue-worker.js +194 -0
- package/dist/queue/queue-worker.js.map +1 -0
- package/dist/queue/registered-background-job.d.ts +11 -0
- package/dist/queue/registered-background-job.d.ts.map +1 -0
- package/dist/queue/registered-background-job.js +17 -0
- package/dist/queue/registered-background-job.js.map +1 -0
- package/dist/queue/report-failed-background-jobs.d.ts +11 -0
- package/dist/queue/report-failed-background-jobs.d.ts.map +1 -0
- package/dist/queue/report-failed-background-jobs.js +22 -0
- package/dist/queue/report-failed-background-jobs.js.map +1 -0
- package/dist/queue/running-job.d.ts +14 -0
- package/dist/queue/running-job.d.ts.map +1 -0
- package/dist/queue/running-job.js +2 -0
- package/dist/queue/running-job.js.map +1 -0
- package/dist/queue/store/claim-request.d.ts +8 -0
- package/dist/queue/store/claim-request.d.ts.map +1 -0
- package/dist/queue/store/claim-request.js +2 -0
- package/dist/queue/store/claim-request.js.map +1 -0
- package/dist/queue/store/claimed-job.d.ts +15 -0
- package/dist/queue/store/claimed-job.d.ts.map +1 -0
- package/dist/queue/store/claimed-job.js +2 -0
- package/dist/queue/store/claimed-job.js.map +1 -0
- package/dist/queue/store/in-memory-job-store.d.ts +40 -0
- package/dist/queue/store/in-memory-job-store.d.ts.map +1 -0
- package/dist/queue/store/in-memory-job-store.js +185 -0
- package/dist/queue/store/in-memory-job-store.js.map +1 -0
- package/dist/queue/store/job-failure.d.ts +8 -0
- package/dist/queue/store/job-failure.d.ts.map +1 -0
- package/dist/queue/store/job-failure.js +2 -0
- package/dist/queue/store/job-failure.js.map +1 -0
- package/dist/queue/store/job-lease.d.ts +9 -0
- package/dist/queue/store/job-lease.d.ts.map +1 -0
- package/dist/queue/store/job-lease.js +2 -0
- package/dist/queue/store/job-lease.js.map +1 -0
- package/dist/queue/store/job-store-stats.d.ts +7 -0
- package/dist/queue/store/job-store-stats.d.ts.map +1 -0
- package/dist/queue/store/job-store-stats.js +2 -0
- package/dist/queue/store/job-store-stats.js.map +1 -0
- package/dist/queue/store/job-store.d.ts +53 -0
- package/dist/queue/store/job-store.d.ts.map +1 -0
- package/dist/queue/store/job-store.js +12 -0
- package/dist/queue/store/job-store.js.map +1 -0
- package/dist/queue/store/job-update.d.ts +7 -0
- package/dist/queue/store/job-update.d.ts.map +1 -0
- package/dist/queue/store/job-update.js +2 -0
- package/dist/queue/store/job-update.js.map +1 -0
- package/dist/queue/store/new-job.d.ts +17 -0
- package/dist/queue/store/new-job.d.ts.map +1 -0
- package/dist/queue/store/new-job.js +2 -0
- package/dist/queue/store/new-job.js.map +1 -0
- package/dist/queue/store/plain-json.d.ts +3 -0
- package/dist/queue/store/plain-json.d.ts.map +1 -0
- package/dist/queue/store/plain-json.js +5 -0
- package/dist/queue/store/plain-json.js.map +1 -0
- package/dist/queue/store/queued-job-of.d.ts +5 -0
- package/dist/queue/store/queued-job-of.d.ts.map +1 -0
- package/dist/queue/store/queued-job-of.js +18 -0
- package/dist/queue/store/queued-job-of.js.map +1 -0
- package/dist/queue/store/stored-job.d.ts +22 -0
- package/dist/queue/store/stored-job.d.ts.map +1 -0
- package/dist/queue/store/stored-job.js +2 -0
- package/dist/queue/store/stored-job.js.map +1 -0
- package/dist/queue/store/tenant-key-of.d.ts +8 -0
- package/dist/queue/store/tenant-key-of.d.ts.map +1 -0
- package/dist/queue/store/tenant-key-of.js +9 -0
- package/dist/queue/store/tenant-key-of.js.map +1 -0
- package/dist/queue/stored-job-queue.d.ts +27 -0
- package/dist/queue/stored-job-queue.d.ts.map +1 -0
- package/dist/queue/stored-job-queue.js +78 -0
- package/dist/queue/stored-job-queue.js.map +1 -0
- package/dist/unless-aborted.d.ts +3 -0
- package/dist/unless-aborted.d.ts.map +1 -0
- package/dist/unless-aborted.js +14 -0
- package/dist/unless-aborted.js.map +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# @ddd-ts-kit/scheduling
|
|
2
2
|
|
|
3
|
-
Scheduled jobs for a project built with the kit. A job is a class
|
|
4
|
-
says when it runs and triggers use cases: it decides nothing, the
|
|
5
|
-
domain. The scheduler opens an execution scope around each run, makes
|
|
6
|
-
application runs a given occurrence, and records what became of it.
|
|
3
|
+
Scheduled jobs and background jobs for a project built with the kit. A scheduled job is a class
|
|
4
|
+
of the application layer that says when it runs and triggers use cases: it decides nothing, the
|
|
5
|
+
business rules stay in the domain. The scheduler opens an execution scope around each run, makes
|
|
6
|
+
sure one instance of the application runs a given occurrence, and records what became of it. A
|
|
7
|
+
background job is enqueued by a use case and run later by the worker of this package (see
|
|
8
|
+
"Background jobs" below).
|
|
7
9
|
|
|
8
10
|
```
|
|
9
11
|
npm i @ddd-ts-kit/scheduling
|
|
@@ -11,7 +13,7 @@ npm i @ddd-ts-kit/scheduling
|
|
|
11
13
|
|
|
12
14
|
| Entry | Holds | Imports |
|
|
13
15
|
|---|---|---|
|
|
14
|
-
| `@ddd-ts-kit/scheduling` | `InProcessJobScheduler`, `nextOccurrence`, `latestOccurrence`, `systemJobTimers`, the `JobTimers` and `JobCheckpoints` ports, `JobTimeoutError`, `JobAbortedError`, `JobLockUnavailableError`, the metric names | the kernel |
|
|
16
|
+
| `@ddd-ts-kit/scheduling` | `InProcessJobScheduler`, `nextOccurrence`, `latestOccurrence`, `systemJobTimers`, the `JobTimers` and `JobCheckpoints` ports, `JobTimeoutError`, `JobAbortedError`, `JobLockUnavailableError`, the metric names; for background jobs `QueueWorker`, `StoredJobQueue`, the `JobStore` port, `InMemoryJobStore`, `reportFailedBackgroundJobs`, `JobInterruptedError`, `InvalidEnqueueError` | the kernel |
|
|
15
17
|
| `@ddd-ts-kit/scheduling/testing` | `ManualJobScheduler`, `ManualJobTimers` | the kernel |
|
|
16
18
|
|
|
17
19
|
The declaration (`@Scheduled`), the port (`JobScheduler`) and the schedule parser live in
|
|
@@ -422,6 +424,67 @@ expect(scheduler.runs.map((run) => run.scheduledAt.toISOString())).toEqual(['202
|
|
|
422
424
|
Another scheduler (on a database, on a queue) implements the `JobScheduler` port of the kernel
|
|
423
425
|
and passes `jobSchedulerContract` of `@ddd-ts-kit/testing/contracts`.
|
|
424
426
|
|
|
427
|
+
## Background jobs
|
|
428
|
+
|
|
429
|
+
Work a use case hands to a worker, to run later: the port (`JobQueue`), the declaration
|
|
430
|
+
(`@Background`) and the payload type live in the kernel; this package runs them. Why and when,
|
|
431
|
+
with the guarantees: [Background jobs](../../docs/concepts/background-jobs.md).
|
|
432
|
+
|
|
433
|
+
| Piece | |
|
|
434
|
+
|---|---|
|
|
435
|
+
| `StoredJobQueue` | the `JobQueue` of the kernel on a `JobStore`: names the job, captures the correlation, the actor, the tenant and the `traceparent` of the work that enqueues, adds it to the store; `find` and `cancel` reach the jobs of the tenant of the work in progress only (those of an elevation's tenants; every job without a tenant) |
|
|
436
|
+
| `JobStore` | the port of the stores: `add`, `claim` (a lease), `heartbeat`, `update` (progress, checkpoint), `complete`, `fail`, `release`, `cancel`, `find`, `retryDead`, `purgeFinished`, `stats`; every report names its attempt (`JobLease`) |
|
|
437
|
+
| `InMemoryJobStore` | the store of tests and of a process without a database: `add`, `cancel` and `retryDead` wait for the commit of the unit of work; `list()` for assertions |
|
|
438
|
+
| `tenantKeyOf(enqueuedBy)` | the tenant part of the idempotency key, for a store that keeps it in a unique index: the tenant, or the empty text |
|
|
439
|
+
| `QueueWorker` | claims and runs the jobs of the queues it has jobs for: `register`, `start`, `stop` (waits for a claim in flight, whose jobs go back uncounted, then for the attempts in progress), `runDue` |
|
|
440
|
+
| `reportFailedBackgroundJobs(reporter)` | the observer that sends an attempt that failed unexpectedly to the error reporter |
|
|
441
|
+
|
|
442
|
+
```ts
|
|
443
|
+
const store = new InMemoryJobStore(); // KnexJobStore, DrizzleJobStore or RedisJobStore in production
|
|
444
|
+
const jobs = new StoredJobQueue({ store, clock, ids, scope, traceparent: captureTraceparent });
|
|
445
|
+
|
|
446
|
+
const worker = new QueueWorker({
|
|
447
|
+
store,
|
|
448
|
+
clock,
|
|
449
|
+
scope,
|
|
450
|
+
logger,
|
|
451
|
+
metrics,
|
|
452
|
+
concurrency: { scheduling: 4, default: 1 },
|
|
453
|
+
onRun: reportFailedBackgroundJobs(errors),
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
worker.register({ name: CompileStatementsBackgroundJob.jobName, options: { maxAttempts: 3 }, run: (payload, execution) => job.run(payload, execution) });
|
|
457
|
+
await worker.start();
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
`@ddd-ts-kit/di` does all of it: `kernelModule({ jobStore })` binds the store, the queue and the
|
|
461
|
+
worker, the declared jobs are registered on the worker, and the worker runs in the processes
|
|
462
|
+
that run the jobs (`jobs: { start: true }`).
|
|
463
|
+
|
|
464
|
+
| Option of `QueueWorker` | Default | |
|
|
465
|
+
|---|---|---|
|
|
466
|
+
| `concurrency` | `1` | attempts of one queue at once in this process: a number, or `{ <queue>: n, default: n }` |
|
|
467
|
+
| `pollIntervalMs` | `1000` | how long an idle queue waits before asking the store again |
|
|
468
|
+
| `graceMs` | `30000` | how long `stop()` waits for the attempts in progress before aborting them; an aborted attempt gives its job back uncounted |
|
|
469
|
+
| `timers` | the runtime | `ManualJobTimers` in a spec |
|
|
470
|
+
|
|
471
|
+
Each attempt is recorded as a `BackgroundJobRun` (`succeeded`, `retried`, `dead`, `released`,
|
|
472
|
+
`interrupted`), logged at `info`, `warn` or `error`, and counted in `background_job_runs_total`
|
|
473
|
+
and `background_job_duration_ms` (`BACKGROUND_RUNS_COUNTER`, `BACKGROUND_DURATION_HISTOGRAM`),
|
|
474
|
+
labelled `job`, `context`, `status` and `error_code`. A store of your own passes
|
|
475
|
+
`jobStoreContract` of `@ddd-ts-kit/testing/contracts`, with its unit of work.
|
|
476
|
+
|
|
477
|
+
## Process managers
|
|
478
|
+
|
|
479
|
+
`StoredProcessRunner` is the `ProcessRunner` of the kernel: `new StoredProcessRunner({ store,
|
|
480
|
+
jobs, commands, unitOfWork })`. A step runs in one unit of work: the instance is loaded, the step
|
|
481
|
+
decides, the timeouts it disarms are cancelled and those it arms are enqueued on the `JobQueue`
|
|
482
|
+
as delayed jobs of the `timeoutJob` of the process (`NoTimeoutJobError` without one), the state
|
|
483
|
+
is saved at the next version, then the commands are sent. `timeout(process, { id, timeout,
|
|
484
|
+
jobId }, step)` runs only while `jobId` is the armed job of that timeout. `@ddd-ts-kit/di` binds
|
|
485
|
+
it on `ProcessStore`, `JobQueue`, `CommandBus` and `UnitOfWork`. See
|
|
486
|
+
[Sagas and process managers](../../docs/concepts/sagas-and-process-managers.md).
|
|
487
|
+
|
|
425
488
|
## Limits
|
|
426
489
|
|
|
427
490
|
- **No persistence of its own.** Runs, outcomes and `lastRun` live in the memory of the
|
|
@@ -433,8 +496,11 @@ and passes `jobSchedulerContract` of `@ddd-ts-kit/testing/contracts`.
|
|
|
433
496
|
possible and rarely wise, as each occurrence costs a lock.
|
|
434
497
|
- **At most once per occurrence is best effort**, as said above. Exactly-once does not exist
|
|
435
498
|
here.
|
|
436
|
-
- **
|
|
437
|
-
not be lost and must be retried
|
|
499
|
+
- **The scheduler is not a queue.** A scheduled job does a bounded amount of work on a
|
|
500
|
+
schedule. Work a command asks for, which must not be lost and must be retried, is a
|
|
501
|
+
background job (above).
|
|
502
|
+
- **The worker:** at least once, no ordering, concurrency per process, polling: see the limits
|
|
503
|
+
of [Background jobs](../../docs/concepts/background-jobs.md).
|
|
438
504
|
- **One process, one event loop.** A job that blocks the loop delays every other job; past
|
|
439
505
|
`lateAfterMs` their occurrences are missed.
|
|
440
506
|
- **Time zone rules are those of the runtime.** A zone whose rules changed needs an updated
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,31 @@ export { JobAbortedError } from './errors/job-aborted-error.js';
|
|
|
8
8
|
export { JobLockUnavailableError } from './errors/job-lock-unavailable-error.js';
|
|
9
9
|
export { JobTimeoutError } from './errors/job-timeout-error.js';
|
|
10
10
|
export { UNEXPECTED_ERROR } from './errors/error-code-of.js';
|
|
11
|
-
export { DURATION_HISTOGRAM, RUNS_COUNTER } from './metric-names.js';
|
|
11
|
+
export { BACKGROUND_DURATION_HISTOGRAM, BACKGROUND_RUNS_COUNTER, DURATION_HISTOGRAM, RUNS_COUNTER, } from './metric-names.js';
|
|
12
12
|
export type { JobRunDetail, JobRunObserver } from './job-run-observer.js';
|
|
13
13
|
export { reportFailedRuns } from './report-failed-runs.js';
|
|
14
|
+
export { QueueWorker } from './queue/queue-worker.js';
|
|
15
|
+
export type { QueueWorkerOptions } from './queue/queue-worker-options.js';
|
|
16
|
+
export { StoredJobQueue, type StoredJobQueueOptions } from './queue/stored-job-queue.js';
|
|
17
|
+
export type { BackgroundJobDefinition } from './queue/background-job-definition.js';
|
|
18
|
+
export type { BackgroundJobObserver } from './queue/background-job-observer.js';
|
|
19
|
+
export type { BackgroundJobOutcome } from './queue/background-job-outcome.js';
|
|
20
|
+
export type { BackgroundJobRun } from './queue/background-job-run.js';
|
|
21
|
+
export { reportFailedBackgroundJobs } from './queue/report-failed-background-jobs.js';
|
|
22
|
+
export { InvalidEnqueueError } from './queue/errors/invalid-enqueue-error.js';
|
|
23
|
+
export { JobInterruptedError } from './queue/errors/job-interrupted-error.js';
|
|
24
|
+
export { UnknownBackgroundJobError } from './queue/errors/unknown-background-job-error.js';
|
|
25
|
+
export { AttemptsExhaustedError } from './queue/errors/attempts-exhausted-error.js';
|
|
26
|
+
export { JobStore } from './queue/store/job-store.js';
|
|
27
|
+
export { InMemoryJobStore } from './queue/store/in-memory-job-store.js';
|
|
28
|
+
export type { ClaimRequest } from './queue/store/claim-request.js';
|
|
29
|
+
export type { ClaimedJob } from './queue/store/claimed-job.js';
|
|
30
|
+
export type { JobFailure } from './queue/store/job-failure.js';
|
|
31
|
+
export type { JobLease } from './queue/store/job-lease.js';
|
|
32
|
+
export type { JobStoreStats } from './queue/store/job-store-stats.js';
|
|
33
|
+
export type { JobUpdate } from './queue/store/job-update.js';
|
|
34
|
+
export type { NewJob } from './queue/store/new-job.js';
|
|
35
|
+
export { tenantKeyOf } from './queue/store/tenant-key-of.js';
|
|
36
|
+
export { StoredProcessRunner, type StoredProcessRunnerOptions } from './process/stored-process-runner.js';
|
|
37
|
+
export { NoTimeoutJobError } from './process/no-timeout-job-error.js';
|
|
14
38
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,KAAK,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AACzG,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,KAAK,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AACzG,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EACL,6BAA6B,EAC7B,uBAAuB,EACvB,kBAAkB,EAClB,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzF,YAAY,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AACpF,YAAY,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAChF,YAAY,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,YAAY,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,gDAAgD,CAAC;AAC3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AACpF,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACxE,YAAY,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,YAAY,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,YAAY,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,YAAY,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,YAAY,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACtE,YAAY,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,YAAY,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,KAAK,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAC1G,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,18 @@ export { JobAbortedError } from './errors/job-aborted-error.js';
|
|
|
8
8
|
export { JobLockUnavailableError } from './errors/job-lock-unavailable-error.js';
|
|
9
9
|
export { JobTimeoutError } from './errors/job-timeout-error.js';
|
|
10
10
|
export { UNEXPECTED_ERROR } from './errors/error-code-of.js';
|
|
11
|
-
export { DURATION_HISTOGRAM, RUNS_COUNTER } from './metric-names.js';
|
|
11
|
+
export { BACKGROUND_DURATION_HISTOGRAM, BACKGROUND_RUNS_COUNTER, DURATION_HISTOGRAM, RUNS_COUNTER, } from './metric-names.js';
|
|
12
12
|
export { reportFailedRuns } from './report-failed-runs.js';
|
|
13
|
+
export { QueueWorker } from './queue/queue-worker.js';
|
|
14
|
+
export { StoredJobQueue } from './queue/stored-job-queue.js';
|
|
15
|
+
export { reportFailedBackgroundJobs } from './queue/report-failed-background-jobs.js';
|
|
16
|
+
export { InvalidEnqueueError } from './queue/errors/invalid-enqueue-error.js';
|
|
17
|
+
export { JobInterruptedError } from './queue/errors/job-interrupted-error.js';
|
|
18
|
+
export { UnknownBackgroundJobError } from './queue/errors/unknown-background-job-error.js';
|
|
19
|
+
export { AttemptsExhaustedError } from './queue/errors/attempts-exhausted-error.js';
|
|
20
|
+
export { JobStore } from './queue/store/job-store.js';
|
|
21
|
+
export { InMemoryJobStore } from './queue/store/in-memory-job-store.js';
|
|
22
|
+
export { tenantKeyOf } from './queue/store/tenant-key-of.js';
|
|
23
|
+
export { StoredProcessRunner } from './process/stored-process-runner.js';
|
|
24
|
+
export { NoTimeoutJobError } from './process/no-timeout-job-error.js';
|
|
13
25
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAqC,MAAM,+BAA+B,CAAC;AACzG,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAwB,MAAM,oCAAoC,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAqC,MAAM,+BAA+B,CAAC;AACzG,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAwB,MAAM,oCAAoC,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EACL,6BAA6B,EAC7B,uBAAuB,EACvB,kBAAkB,EAClB,YAAY,GACb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAA8B,MAAM,6BAA6B,CAAC;AAKzF,OAAO,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,gDAAgD,CAAC;AAC3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AACpF,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAQxE,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAmC,MAAM,oCAAoC,CAAC;AAC1G,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC"}
|
package/dist/job-runner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-runner.d.ts","sourceRoot":"","sources":["../src/job-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,KAAK,EACV,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,IAAI,EACT,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"job-runner.d.ts","sourceRoot":"","sources":["../src/job-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,KAAK,EACV,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,IAAI,EACT,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIzD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,+EAA+E;IAC/E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,gDAAgD;IAChD,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC;CACpC;AASD,yFAAyF;AACzF,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAF3B,YACmB,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,WAAW,EACpC;IAEJ,YAAY,IAAI,OAAO,CAEtB;IAED,4DAA4D;IACtD,GAAG,CAAC,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAQrE;YAOa,KAAK;YAkBL,OAAO;IAsBrB,OAAO,CAAC,UAAU;YAYJ,OAAO;YAUP,QAAQ;CAiBvB"}
|
package/dist/job-runner.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { executionContextOfJob, } from '@ddd-ts-kit/kernel';
|
|
2
2
|
import { JobLockUnavailableError } from './errors/job-lock-unavailable-error.js';
|
|
3
3
|
import { JobTimeoutError } from './errors/job-timeout-error.js';
|
|
4
|
+
import { unlessAborted } from './unless-aborted.js';
|
|
4
5
|
/** Runs one occurrence: the lock of the occurrence, the execution scope, the timeout. */
|
|
5
6
|
export class JobRunner {
|
|
6
7
|
options;
|
|
@@ -108,17 +109,4 @@ async function eachTenant(tenants, signal, run) {
|
|
|
108
109
|
throw failures[0];
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
|
-
/** A job that ignores its signal is left behind: the run ends when the signal is aborted. */
|
|
112
|
-
function unlessAborted(signal, work) {
|
|
113
|
-
return new Promise((resolve, reject) => {
|
|
114
|
-
signal.addEventListener('abort', () => {
|
|
115
|
-
reject(reasonOf(signal));
|
|
116
|
-
}, { once: true });
|
|
117
|
-
work.then(resolve, reject);
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
function reasonOf(signal) {
|
|
121
|
-
const reason = signal.reason;
|
|
122
|
-
return reason instanceof Error ? reason : new Error('The run was aborted.');
|
|
123
|
-
}
|
|
124
112
|
//# sourceMappingURL=job-runner.js.map
|
package/dist/job-runner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-runner.js","sourceRoot":"","sources":["../src/job-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAOtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"job-runner.js","sourceRoot":"","sources":["../src/job-runner.ts"],"names":[],"mappings":"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"}
|
package/dist/metric-names.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export declare const RUNS_COUNTER = "scheduled_job_runs_total";
|
|
2
2
|
export declare const DURATION_HISTOGRAM = "scheduled_job_duration_ms";
|
|
3
|
+
export declare const BACKGROUND_RUNS_COUNTER = "background_job_runs_total";
|
|
4
|
+
export declare const BACKGROUND_DURATION_HISTOGRAM = "background_job_duration_ms";
|
|
3
5
|
//# sourceMappingURL=metric-names.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metric-names.d.ts","sourceRoot":"","sources":["../src/metric-names.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,6BAA6B,CAAC;AAEvD,eAAO,MAAM,kBAAkB,8BAA8B,CAAC"}
|
|
1
|
+
{"version":3,"file":"metric-names.d.ts","sourceRoot":"","sources":["../src/metric-names.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,6BAA6B,CAAC;AAEvD,eAAO,MAAM,kBAAkB,8BAA8B,CAAC;AAE9D,eAAO,MAAM,uBAAuB,8BAA8B,CAAC;AAEnE,eAAO,MAAM,6BAA6B,+BAA+B,CAAC"}
|
package/dist/metric-names.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export const RUNS_COUNTER = 'scheduled_job_runs_total';
|
|
2
2
|
export const DURATION_HISTOGRAM = 'scheduled_job_duration_ms';
|
|
3
|
+
export const BACKGROUND_RUNS_COUNTER = 'background_job_runs_total';
|
|
4
|
+
export const BACKGROUND_DURATION_HISTOGRAM = 'background_job_duration_ms';
|
|
3
5
|
//# sourceMappingURL=metric-names.js.map
|
package/dist/metric-names.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metric-names.js","sourceRoot":"","sources":["../src/metric-names.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,0BAA0B,CAAC;AAEvD,MAAM,CAAC,MAAM,kBAAkB,GAAG,2BAA2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"metric-names.js","sourceRoot":"","sources":["../src/metric-names.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,0BAA0B,CAAC;AAEvD,MAAM,CAAC,MAAM,kBAAkB,GAAG,2BAA2B,CAAC;AAE9D,MAAM,CAAC,MAAM,uBAAuB,GAAG,2BAA2B,CAAC;AAEnE,MAAM,CAAC,MAAM,6BAA6B,GAAG,4BAA4B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-timeout-job-error.d.ts","sourceRoot":"","sources":["../../src/process/no-timeout-job-error.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,oBAAoB;IAEjC,YAAY,OAAO,EAAE,MAAM,EAM1B;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** A process armed a timeout and names no background job to deliver it. */
|
|
2
|
+
export class NoTimeoutJobError extends Error {
|
|
3
|
+
code = 'NO_TIMEOUT_JOB';
|
|
4
|
+
constructor(process) {
|
|
5
|
+
super(`Process "${process}" arms a timeout and has no static timeoutJob: name the background job that delivers it.`);
|
|
6
|
+
this.name = 'NoTimeoutJobError';
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=no-timeout-job-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-timeout-job-error.js","sourceRoot":"","sources":["../../src/process/no-timeout-job-error.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,IAAI,GAAG,gBAAgB,CAAC;IAEjC,YAAY,OAAe;QACzB,KAAK,CACH,YAAY,OAAO,0FAA0F,CAC9G,CAAC;QAEF,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type CommandBus, type JobQueue, type ProcessDecision, type ProcessRunner, type ProcessStore, type ProcessTimeoutDue, type ProcessType, type UnitOfWork } from '@ddd-ts-kit/kernel';
|
|
2
|
+
export interface StoredProcessRunnerOptions {
|
|
3
|
+
readonly store: ProcessStore;
|
|
4
|
+
/** Where the timeouts are enqueued, as delayed background jobs. */
|
|
5
|
+
readonly jobs: JobQueue;
|
|
6
|
+
readonly commands: CommandBus;
|
|
7
|
+
/** The step, its state, its timeouts and its commands commit together. */
|
|
8
|
+
readonly unitOfWork: UnitOfWork;
|
|
9
|
+
}
|
|
10
|
+
/** The `ProcessRunner` of the kernel on a `ProcessStore` and a `JobQueue`. */
|
|
11
|
+
export declare class StoredProcessRunner implements ProcessRunner {
|
|
12
|
+
private readonly options;
|
|
13
|
+
constructor(options: StoredProcessRunnerOptions);
|
|
14
|
+
run<State>(process: ProcessType<State>, id: string, step: (current: State | undefined) => ProcessDecision<State> | undefined): Promise<void>;
|
|
15
|
+
timeout<State>(process: ProcessType<State>, due: ProcessTimeoutDue & {
|
|
16
|
+
readonly jobId: string;
|
|
17
|
+
}, step: (current: State) => ProcessDecision<State> | undefined): Promise<void>;
|
|
18
|
+
/** Disarms, arms, saves, then sends the commands: everything in the unit of work of the step. */
|
|
19
|
+
private apply;
|
|
20
|
+
private disarm;
|
|
21
|
+
/** A timeout armed again replaces the one of the same name, whose job no longer counts. */
|
|
22
|
+
private arm;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=stored-process-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stored-process-runner.d.ts","sourceRoot":"","sources":["../../src/process/stored-process-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAEhB,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAG5B,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CACjC;AAWD,8EAA8E;AAC9E,qBAAa,mBAAoB,YAAW,aAAa;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAApC,YAA6B,OAAO,EAAE,0BAA0B,EAAI;IAEpE,GAAG,CAAC,KAAK,EACP,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,EAC3B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,GAAG,SAAS,KAAK,eAAe,CAAC,KAAK,CAAC,GAAG,SAAS,GACvE,OAAO,CAAC,IAAI,CAAC,CAaf;IAED,OAAO,CAAC,KAAK,EACX,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,EAC3B,GAAG,EAAE,iBAAiB,GAAG;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EACnD,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,KAAK,eAAe,CAAC,KAAK,CAAC,GAAG,SAAS,GAC3D,OAAO,CAAC,IAAI,CAAC,CAaf;IAED,iGAAiG;YACnF,KAAK;YA4BL,MAAM;IAYpB,2FAA2F;YAC7E,GAAG;CAqBlB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { UnreadableProcessStateError, } from '@ddd-ts-kit/kernel';
|
|
2
|
+
import { NoTimeoutJobError } from './no-timeout-job-error.js';
|
|
3
|
+
/** The `ProcessRunner` of the kernel on a `ProcessStore` and a `JobQueue`. */
|
|
4
|
+
export class StoredProcessRunner {
|
|
5
|
+
options;
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this.options = options;
|
|
8
|
+
}
|
|
9
|
+
run(process, id, step) {
|
|
10
|
+
return this.options.unitOfWork.run(async () => {
|
|
11
|
+
const stored = await this.options.store.load(process.processName, id);
|
|
12
|
+
if (stored?.ended === true) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const current = stored === undefined ? undefined : stateOf(process, stored);
|
|
16
|
+
const instance = { name: process.processName, id, stored, timeouts: stored?.timeouts ?? {} };
|
|
17
|
+
await this.apply(process, instance, step(current));
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
timeout(process, due, step) {
|
|
21
|
+
return this.options.unitOfWork.run(async () => {
|
|
22
|
+
const stored = await this.options.store.load(process.processName, due.id);
|
|
23
|
+
if (stored === undefined || stored.ended || stored.timeouts[due.timeout] !== due.jobId) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const timeouts = without(stored.timeouts, [due.timeout]);
|
|
27
|
+
const instance = { name: process.processName, id: due.id, stored, timeouts };
|
|
28
|
+
await this.apply(process, instance, step(stateOf(process, stored)));
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** Disarms, arms, saves, then sends the commands: everything in the unit of work of the step. */
|
|
32
|
+
async apply(process, instance, decision) {
|
|
33
|
+
if (decision === undefined) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const disarmed = await this.disarm(instance.timeouts, decision.cancel ?? []);
|
|
37
|
+
const timeouts = await this.arm(process, { ...instance, timeouts: disarmed }, decision);
|
|
38
|
+
const { name, id, stored } = instance;
|
|
39
|
+
const version = (stored?.version ?? 0) + 1;
|
|
40
|
+
await this.options.store.save({
|
|
41
|
+
name,
|
|
42
|
+
id,
|
|
43
|
+
state: decision.state,
|
|
44
|
+
version,
|
|
45
|
+
ended: decision.ended === true,
|
|
46
|
+
timeouts,
|
|
47
|
+
});
|
|
48
|
+
for (const command of decision.commands ?? []) {
|
|
49
|
+
await this.options.commands.execute(command);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async disarm(timeouts, names) {
|
|
53
|
+
for (const name of names) {
|
|
54
|
+
const jobId = timeouts[name];
|
|
55
|
+
if (jobId !== undefined) {
|
|
56
|
+
await this.options.jobs.cancel(jobId);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return without(timeouts, names);
|
|
60
|
+
}
|
|
61
|
+
/** A timeout armed again replaces the one of the same name, whose job no longer counts. */
|
|
62
|
+
async arm(process, instance, decision) {
|
|
63
|
+
let armed = instance.timeouts;
|
|
64
|
+
for (const { name, at } of decision.timeouts ?? []) {
|
|
65
|
+
armed = await this.disarm(armed, [name]);
|
|
66
|
+
const { id: jobId } = await this.options.jobs.enqueue(timeoutJobOf(process), { id: instance.id, timeout: name }, { runAt: at });
|
|
67
|
+
armed = { ...armed, [name]: jobId };
|
|
68
|
+
}
|
|
69
|
+
return armed;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function stateOf(process, stored) {
|
|
73
|
+
if (!process.isState(stored.state)) {
|
|
74
|
+
throw new UnreadableProcessStateError(process.processName, stored.id);
|
|
75
|
+
}
|
|
76
|
+
return stored.state;
|
|
77
|
+
}
|
|
78
|
+
function without(timeouts, names) {
|
|
79
|
+
return Object.fromEntries(Object.entries(timeouts).filter(([name]) => !names.includes(name)));
|
|
80
|
+
}
|
|
81
|
+
/** The background job that delivers the timeouts: the runner only names it, the context declares it. */
|
|
82
|
+
function timeoutJobOf(process) {
|
|
83
|
+
const { timeoutJob } = process;
|
|
84
|
+
if (timeoutJob === undefined) {
|
|
85
|
+
throw new NoTimeoutJobError(process.processName);
|
|
86
|
+
}
|
|
87
|
+
return { jobName: timeoutJob, prototype: { run: () => Promise.resolve() } };
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=stored-process-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stored-process-runner.js","sourceRoot":"","sources":["../../src/process/stored-process-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BackgroundJobExecution, BackgroundJobOptions } from '@ddd-ts-kit/kernel';
|
|
2
|
+
/** A background job as a worker receives it. */
|
|
3
|
+
export interface BackgroundJobDefinition {
|
|
4
|
+
/** `<context>.<job-name>`: its queue is the context. */
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly options?: BackgroundJobOptions;
|
|
7
|
+
readonly run: (payload: unknown, execution: BackgroundJobExecution) => Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=background-job-definition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-job-definition.d.ts","sourceRoot":"","sources":["../../src/queue/background-job-definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAEvF,gDAAgD;AAChD,MAAM,WAAW,uBAAuB;IACtC,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-job-definition.js","sourceRoot":"","sources":["../../src/queue/background-job-definition.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { BackgroundJobRun } from './background-job-run.js';
|
|
2
|
+
/** Told of every attempt, with what the run threw when it failed: for an error tracker, or a test. */
|
|
3
|
+
export type BackgroundJobObserver = (run: BackgroundJobRun, error?: unknown) => void;
|
|
4
|
+
//# sourceMappingURL=background-job-observer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-job-observer.d.ts","sourceRoot":"","sources":["../../src/queue/background-job-observer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,sGAAsG;AACtG,MAAM,MAAM,qBAAqB,GAAG,CAAC,GAAG,EAAE,gBAAgB,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-job-observer.js","sourceRoot":"","sources":["../../src/queue/background-job-observer.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* - `succeeded`: the run ended and the job is over.
|
|
3
|
+
* - `retried`: the run failed and the job waits for its next attempt.
|
|
4
|
+
* - `dead`: the run failed and no attempt is left.
|
|
5
|
+
* - `released`: the worker stopped before the run ended; the job waits again, the attempt not counted.
|
|
6
|
+
* - `interrupted`: the job was cancelled, or another worker claimed it, while it ran.
|
|
7
|
+
*/
|
|
8
|
+
export type BackgroundJobOutcome = 'succeeded' | 'retried' | 'dead' | 'released' | 'interrupted';
|
|
9
|
+
//# sourceMappingURL=background-job-outcome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-job-outcome.d.ts","sourceRoot":"","sources":["../../src/queue/background-job-outcome.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-job-outcome.js","sourceRoot":"","sources":["../../src/queue/background-job-outcome.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Logger, Metrics } from '@ddd-ts-kit/kernel';
|
|
2
|
+
import type { BackgroundJobObserver } from './background-job-observer.js';
|
|
3
|
+
import type { BackgroundJobRun } from './background-job-run.js';
|
|
4
|
+
export interface BackgroundJobRecorderOptions {
|
|
5
|
+
readonly logger: Logger;
|
|
6
|
+
readonly metrics: Metrics;
|
|
7
|
+
readonly onRun?: BackgroundJobObserver;
|
|
8
|
+
}
|
|
9
|
+
/** Says what became of each attempt, to the log, the metrics and the observer. Never the message of an error. */
|
|
10
|
+
export declare class BackgroundJobRecorder {
|
|
11
|
+
private readonly options;
|
|
12
|
+
constructor(options: BackgroundJobRecorderOptions);
|
|
13
|
+
record(run: BackgroundJobRun, error?: unknown): BackgroundJobRun;
|
|
14
|
+
/** The worker itself stumbled, claiming or reporting: it goes on, and the lease brings the job back. */
|
|
15
|
+
fault(queue: string, error: unknown): void;
|
|
16
|
+
private measure;
|
|
17
|
+
private log;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=background-job-recorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-job-recorder.d.ts","sourceRoot":"","sources":["../../src/queue/background-job-recorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,MAAM,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE/E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAE1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,qBAAqB,CAAC;CACxC;AAED,iHAAiH;AACjH,qBAAa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAApC,YAA6B,OAAO,EAAE,4BAA4B,EAAI;IAEtE,MAAM,CAAC,GAAG,EAAE,gBAAgB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAc/D;IAED,wGAAwG;IACxG,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAQzC;IAED,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,GAAG;CAqBZ"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { BACKGROUND_DURATION_HISTOGRAM, BACKGROUND_RUNS_COUNTER } from '../metric-names.js';
|
|
2
|
+
/** Says what became of each attempt, to the log, the metrics and the observer. Never the message of an error. */
|
|
3
|
+
export class BackgroundJobRecorder {
|
|
4
|
+
options;
|
|
5
|
+
constructor(options) {
|
|
6
|
+
this.options = options;
|
|
7
|
+
}
|
|
8
|
+
record(run, error) {
|
|
9
|
+
quietly(() => {
|
|
10
|
+
this.measure(run);
|
|
11
|
+
});
|
|
12
|
+
quietly(() => {
|
|
13
|
+
this.log(run, error);
|
|
14
|
+
});
|
|
15
|
+
quietly(() => {
|
|
16
|
+
this.options.onRun?.(run, error);
|
|
17
|
+
});
|
|
18
|
+
return run;
|
|
19
|
+
}
|
|
20
|
+
/** The worker itself stumbled, claiming or reporting: it goes on, and the lease brings the job back. */
|
|
21
|
+
fault(queue, error) {
|
|
22
|
+
quietly(() => {
|
|
23
|
+
this.options.logger.error('Background jobs could not be followed', {
|
|
24
|
+
queue,
|
|
25
|
+
errorType: typeOf(error),
|
|
26
|
+
...codeOf(error),
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
measure(run) {
|
|
31
|
+
const labels = { job: run.job, context: contextOf(run.job), status: run.outcome, error_code: run.errorCode };
|
|
32
|
+
this.options.metrics.counter(BACKGROUND_RUNS_COUNTER).increment(labels);
|
|
33
|
+
this.options.metrics.histogram(BACKGROUND_DURATION_HISTOGRAM).record(run.durationMs, labels);
|
|
34
|
+
}
|
|
35
|
+
log(run, error) {
|
|
36
|
+
const level = LEVELS[run.outcome];
|
|
37
|
+
if (!this.options.logger.isLevelEnabled(level)) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const fields = {
|
|
41
|
+
job: run.job,
|
|
42
|
+
jobId: run.jobId,
|
|
43
|
+
context: contextOf(run.job),
|
|
44
|
+
attempt: run.attempt,
|
|
45
|
+
outcome: run.outcome,
|
|
46
|
+
durationMs: run.durationMs,
|
|
47
|
+
correlationId: run.correlationId,
|
|
48
|
+
...(run.errorCode === undefined ? {} : { errorCode: run.errorCode }),
|
|
49
|
+
...(error === undefined ? {} : { errorType: typeOf(error) }),
|
|
50
|
+
};
|
|
51
|
+
this.options.logger[level](`Background job ${WORDS[run.outcome]}`, fields);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function contextOf(job) {
|
|
55
|
+
return job.split('.', 1).join('');
|
|
56
|
+
}
|
|
57
|
+
function typeOf(error) {
|
|
58
|
+
return error instanceof Error ? error.constructor.name : typeof error;
|
|
59
|
+
}
|
|
60
|
+
function codeOf(error) {
|
|
61
|
+
const code = typeof error === 'object' && error !== null ? Reflect.get(error, 'code') : undefined;
|
|
62
|
+
return typeof code === 'string' ? { errorCode: code } : {};
|
|
63
|
+
}
|
|
64
|
+
/** What records a run must not break it: a logger, a meter or an observer that throws is left alone. */
|
|
65
|
+
function quietly(tell) {
|
|
66
|
+
try {
|
|
67
|
+
tell();
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const LEVELS = {
|
|
74
|
+
succeeded: 'info',
|
|
75
|
+
retried: 'warn',
|
|
76
|
+
dead: 'error',
|
|
77
|
+
released: 'info',
|
|
78
|
+
interrupted: 'warn',
|
|
79
|
+
};
|
|
80
|
+
const WORDS = {
|
|
81
|
+
succeeded: 'succeeded',
|
|
82
|
+
retried: 'failed: it will be tried again',
|
|
83
|
+
dead: 'failed for good: it is dead',
|
|
84
|
+
released: 'released: the worker stopped before it ended',
|
|
85
|
+
interrupted: 'interrupted: cancelled, or claimed by another worker',
|
|
86
|
+
};
|
|
87
|
+
//# sourceMappingURL=background-job-recorder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-job-recorder.js","sourceRoot":"","sources":["../../src/queue/background-job-recorder.ts"],"names":[],"mappings":"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"}
|