velocious 1.0.606 → 1.0.608
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 +45 -2
- package/build/background-jobs/job-semantics.js +145 -0
- package/build/background-jobs/local-adapter.js +161 -0
- package/build/background-jobs/local-dispatcher.js +418 -0
- package/build/background-jobs/local-job-registry.js +59 -0
- package/build/background-jobs/local-store.js +1220 -0
- package/build/background-jobs/main.js +2 -1
- package/build/background-jobs/store.js +97 -100
- package/build/background-jobs/types.js +28 -1
- package/build/background-jobs/worker.js +19 -14
- package/build/configuration-types.js +3 -1
- package/build/configuration.js +16 -1
- package/build/database/drivers/sqlite/index.js +46 -41
- package/build/environment-handlers/browser.js +10 -0
- package/build/src/background-jobs/job-semantics.d.ts +65 -0
- package/build/src/background-jobs/job-semantics.d.ts.map +1 -0
- package/build/src/background-jobs/job-semantics.js +125 -0
- package/build/src/background-jobs/local-adapter.d.ts +161 -0
- package/build/src/background-jobs/local-adapter.d.ts.map +1 -0
- package/build/src/background-jobs/local-adapter.js +141 -0
- package/build/src/background-jobs/local-dispatcher.d.ts +185 -0
- package/build/src/background-jobs/local-dispatcher.d.ts.map +1 -0
- package/build/src/background-jobs/local-dispatcher.js +383 -0
- package/build/src/background-jobs/local-job-registry.d.ts +26 -0
- package/build/src/background-jobs/local-job-registry.d.ts.map +1 -0
- package/build/src/background-jobs/local-job-registry.js +51 -0
- package/build/src/background-jobs/local-store.d.ts +364 -0
- package/build/src/background-jobs/local-store.d.ts.map +1 -0
- package/build/src/background-jobs/local-store.js +1079 -0
- package/build/src/background-jobs/main.d.ts.map +1 -1
- package/build/src/background-jobs/main.js +3 -2
- package/build/src/background-jobs/store.d.ts +17 -9
- package/build/src/background-jobs/store.d.ts.map +1 -1
- package/build/src/background-jobs/store.js +75 -91
- package/build/src/background-jobs/types.d.ts +107 -2
- package/build/src/background-jobs/types.d.ts.map +1 -1
- package/build/src/background-jobs/types.js +29 -2
- package/build/src/background-jobs/worker.d.ts +15 -7
- package/build/src/background-jobs/worker.d.ts.map +1 -1
- package/build/src/background-jobs/worker.js +20 -15
- package/build/src/configuration-types.d.ts +9 -2
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +4 -2
- package/build/src/configuration.d.ts +5 -0
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +15 -2
- package/build/src/database/drivers/sqlite/index.d.ts +8 -0
- package/build/src/database/drivers/sqlite/index.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/index.js +47 -41
- package/build/src/environment-handlers/browser.d.ts +9 -0
- package/build/src/environment-handlers/browser.d.ts.map +1 -1
- package/build/src/environment-handlers/browser.js +10 -1
- package/build/src/testing/test-runner.d.ts +42 -10
- package/build/src/testing/test-runner.d.ts.map +1 -1
- package/build/src/testing/test-runner.js +135 -35
- package/build/testing/test-runner.js +141 -33
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/scripts/test-browser.js +5 -1
- package/src/background-jobs/job-semantics.js +145 -0
- package/src/background-jobs/local-adapter.js +161 -0
- package/src/background-jobs/local-dispatcher.js +418 -0
- package/src/background-jobs/local-job-registry.js +59 -0
- package/src/background-jobs/local-store.js +1220 -0
- package/src/background-jobs/main.js +2 -1
- package/src/background-jobs/store.js +97 -100
- package/src/background-jobs/types.js +28 -1
- package/src/background-jobs/worker.js +19 -14
- package/src/configuration-types.js +3 -1
- package/src/configuration.js +16 -1
- package/src/database/drivers/sqlite/index.js +46 -41
- package/src/environment-handlers/browser.js +10 -0
- package/src/testing/test-runner.js +141 -33
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
* Cross-process broadcast bus for `broadcastToChannel` via `velocious beacon`, including background job runner processes (see [docs/beacon.md](docs/beacon.md))
|
|
35
35
|
* Configurable HTTP server worker handlers plus backpressured, descriptor-only file responses with completion callbacks (see [docs/http-server.md](docs/http-server.md))
|
|
36
36
|
* Default-on buffered HTTP response compression with Brotli/gzip content negotiation, global and per-response opt-outs, and HEAD-correct representation headers (see [docs/http-server.md](docs/http-server.md#response-compression))
|
|
37
|
-
* Background jobs with
|
|
37
|
+
* Background jobs with Node SQL/TCP workers plus a Browser/Expo local SQLite store and in-process dispatcher, failure events, and authorized database-scoped dashboard count snapshots/deltas (see [docs/background-jobs.md](docs/background-jobs.md), [docs/local-background-jobs.md](docs/local-background-jobs.md), and [docs/background-jobs-dashboard.md](docs/background-jobs-dashboard.md))
|
|
38
38
|
* Durable one-off background-job scheduling with exact epoch timestamps (see [docs/scheduled-background-job-enqueue.md](docs/scheduled-background-job-enqueue.md))
|
|
39
39
|
* Rails-style request and database query logging (see [docs/logging.md](docs/logging.md))
|
|
40
40
|
* EJS-backed mailers with delivery, queueing, and payload rendering support (see [docs/mailers.md](docs/mailers.md))
|
|
@@ -178,6 +178,17 @@ npx velocious test --include-tag fast,api
|
|
|
178
178
|
npx velocious test --exclude-tag slow
|
|
179
179
|
```
|
|
180
180
|
|
|
181
|
+
`*.browser-spec.js` files remain eligible for both the Node database matrix and
|
|
182
|
+
the browser runner. Add the reserved `browser-only` tag only when a suite requires
|
|
183
|
+
the real browser environment; the Node runner discovers the file but does not
|
|
184
|
+
execute its tagged tests.
|
|
185
|
+
|
|
186
|
+
```js
|
|
187
|
+
describe("Browser integration", {tags: ["browser-only"]}, () => {
|
|
188
|
+
it("uses browser runtime behavior", async () => {})
|
|
189
|
+
})
|
|
190
|
+
```
|
|
191
|
+
|
|
181
192
|
Target a test by line number or description.
|
|
182
193
|
|
|
183
194
|
```bash
|
|
@@ -2331,6 +2342,38 @@ synchronous factory. See [runtime modes and adapters](docs/background-jobs.md#ru
|
|
|
2331
2342
|
for the contract, lifecycle, Node TCP/wake behavior, the explicit
|
|
2332
2343
|
`platform-job.js` browser/Expo entry, and SQL-only compatibility boundaries.
|
|
2333
2344
|
|
|
2345
|
+
Browser and Expo configurations have a built-in local SQLite adapter in
|
|
2346
|
+
`"background"` mode. Register portable classes statically; no main process,
|
|
2347
|
+
worker, socket, or child process is started:
|
|
2348
|
+
|
|
2349
|
+
```js
|
|
2350
|
+
import VelociousJob from "velocious/build/src/background-jobs/platform-job.js"
|
|
2351
|
+
|
|
2352
|
+
class UploadPendingChangesJob extends VelociousJob {
|
|
2353
|
+
async perform(projectId) {
|
|
2354
|
+
await uploadPendingChanges(projectId)
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
export default new Configuration({
|
|
2359
|
+
backgroundJobs: {
|
|
2360
|
+
databaseIdentifier: "default",
|
|
2361
|
+
jobClasses: [UploadPendingChangesJob],
|
|
2362
|
+
maxConcurrentInlineJobs: 4,
|
|
2363
|
+
queues: {uploads: {maxConcurrent: 2, priority: 10}}
|
|
2364
|
+
}
|
|
2365
|
+
})
|
|
2366
|
+
```
|
|
2367
|
+
|
|
2368
|
+
Local enqueue participates in an existing application transaction and wakes the
|
|
2369
|
+
dispatcher only after commit. It supports queue caps/priorities, explicit
|
|
2370
|
+
concurrency, queued deduplication, one-off scheduling, retries/backoff,
|
|
2371
|
+
`rescheduleIn`, fenced acknowledgements, graceful close/reopen, interrupted-job
|
|
2372
|
+
recovery, and the existing SQL.js persistence backends. It supports one active
|
|
2373
|
+
configuration-owned adapter per app/database; OS background execution and
|
|
2374
|
+
multi-tab leadership are outside this backend. See
|
|
2375
|
+
[local background jobs](docs/local-background-jobs.md).
|
|
2376
|
+
|
|
2334
2377
|
Or via env vars:
|
|
2335
2378
|
|
|
2336
2379
|
```
|
|
@@ -2362,7 +2405,7 @@ concurrency and per-job connection scopes are unchanged.
|
|
|
2362
2405
|
|
|
2363
2406
|
`maxConcurrentForkedJobs` (default: `4`) caps how many out-of-process `executionMode: "forked"` or `executionMode: "spawned"` jobs one worker may keep in flight. Forked jobs use `child_process.fork()` with an attached IPC channel. After the main process acknowledges their durable status report, forked and spawned one-shot runners exit without waiting for graceful Beacon/database teardown; the OS closes their process-owned resources. A missing or rejected status acknowledgement makes the runner exit as failed instead of reporting clean success. Spawned jobs use the legacy `background-jobs-runner` CLI process via `child_process.spawn()` and are only for callers that intentionally want that spawned behavior.
|
|
2364
2407
|
|
|
2365
|
-
`jobTimeoutMs` (or `VELOCIOUS_BACKGROUND_JOBS_JOB_TIMEOUT_MS`, milliseconds; default: disabled) is a wall-clock backstop for `"forked"` and `"pooled"` jobs. A job still running after the timeout is terminated (`SIGTERM`, then `SIGKILL` after the reaping grace) and reported `failed`, so a genuinely-hung job can't pin a worker's capacity — and its whole-app boot and DB connections — indefinitely (notably a retired-release worker draining after a deploy). For a **pooled** job the whole child running it is killed, so its concurrent in-flight siblings on that child are also reported `failed` and requeued — a hung JS job can't be cancelled any other way — before a replacement child is spawned.
|
|
2408
|
+
`jobTimeoutMs` (or `VELOCIOUS_BACKGROUND_JOBS_JOB_TIMEOUT_MS`, milliseconds; default: disabled) is a wall-clock backstop for `"forked"` and `"pooled"` jobs. A job still running after the timeout is terminated (`SIGTERM`, then `SIGKILL` after the reaping grace) and reported `failed`, so a genuinely-hung job can't pin a worker's capacity — and its whole-app boot and DB connections — indefinitely (notably a retired-release worker draining after a deploy). For a **pooled** job the whole child running it is killed, so its concurrent in-flight siblings on that child are also reported `failed` and requeued — a hung JS job can't be cancelled any other way — before a replacement child is spawned. Set `options.timeoutMs` to a positive integer no greater than `2_147_483_647` for a per-job wall-clock timeout that overrides the worker default; a non-positive finite value disables the backstop for that job. Invalid types, non-finite values, fractions, and larger values are rejected before persistence. Omit it to retain the worker-level fallback. `"inline"` jobs are not covered — they share the worker's process and can't be killed without killing the worker. See [docs/background-jobs.md](docs/background-jobs.md#job-timeout-hung-runner-backstop).
|
|
2366
2409
|
|
|
2367
2410
|
### Dispatch strategy
|
|
2368
2411
|
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import VelociousError from "../velocious-error.js"
|
|
4
|
+
|
|
5
|
+
export const DEFAULT_BACKGROUND_JOB_EXECUTION_MODE = "pooled"
|
|
6
|
+
export const DEFAULT_BACKGROUND_JOB_MAX_RETRIES = 10
|
|
7
|
+
export const DEFAULT_BACKGROUND_JOB_QUEUE = "default"
|
|
8
|
+
export const QUEUE_CONCURRENCY_KEY_PREFIX = "queue:"
|
|
9
|
+
/** @type {import("./types.js").BackgroundJobExecutionMode[]} */
|
|
10
|
+
export const BACKGROUND_JOB_EXECUTION_MODES = ["inline", "forked", "pooled", "spawned"]
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Normalizes a job queue.
|
|
14
|
+
* @param {import("./types.js").BackgroundJobOptions} [options] - Job options.
|
|
15
|
+
* @returns {string} - Queue name.
|
|
16
|
+
*/
|
|
17
|
+
export function normalizeBackgroundJobQueue(options) {
|
|
18
|
+
const queue = options?.queue
|
|
19
|
+
|
|
20
|
+
if (typeof queue === "string" && queue.trim().length > 0) return queue.trim()
|
|
21
|
+
|
|
22
|
+
return DEFAULT_BACKGROUND_JOB_QUEUE
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Normalizes an explicit execution mode while retaining the Node default.
|
|
27
|
+
* @param {Omit<import("./types.js").BackgroundJobOptions, "executionMode"> & {executionMode?: string}} options - Job options.
|
|
28
|
+
* @param {import("./types.js").BackgroundJobExecutionMode} [defaultExecutionMode] - Default mode.
|
|
29
|
+
* @param {import("./types.js").BackgroundJobExecutionMode[]} [supportedExecutionModes] - Modes accepted by the caller.
|
|
30
|
+
* @returns {import("./types.js").BackgroundJobExecutionMode} - Execution mode.
|
|
31
|
+
*/
|
|
32
|
+
export function normalizeBackgroundJobExecutionMode(options = {}, defaultExecutionMode = DEFAULT_BACKGROUND_JOB_EXECUTION_MODE, supportedExecutionModes = BACKGROUND_JOB_EXECUTION_MODES) {
|
|
33
|
+
if ("forked" in options) {
|
|
34
|
+
throw new Error("The background job `forked` option was removed; pass `executionMode` (\"inline\", \"forked\", \"pooled\", or \"spawned\") instead")
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const requestedExecutionMode = options.executionMode || defaultExecutionMode
|
|
38
|
+
/** @type {import("./types.js").BackgroundJobExecutionMode | undefined} */
|
|
39
|
+
let executionMode
|
|
40
|
+
|
|
41
|
+
for (const candidate of BACKGROUND_JOB_EXECUTION_MODES) {
|
|
42
|
+
if (candidate === requestedExecutionMode) executionMode = candidate
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!executionMode) throw new Error(`Invalid background job executionMode: ${requestedExecutionMode}`)
|
|
46
|
+
|
|
47
|
+
if (!supportedExecutionModes.includes(executionMode)) {
|
|
48
|
+
throw new Error(`Background job executionMode "${executionMode}" is not supported by the local background-jobs adapter`)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return executionMode
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Validates and normalizes a retry cap.
|
|
56
|
+
* @param {number | null | undefined} maxRetries - Requested retry cap.
|
|
57
|
+
* @returns {number} - Retry cap.
|
|
58
|
+
*/
|
|
59
|
+
export function normalizeBackgroundJobMaxRetries(maxRetries) {
|
|
60
|
+
if (typeof maxRetries === "number" && Number.isFinite(maxRetries) && maxRetries >= 0) {
|
|
61
|
+
return Math.floor(maxRetries)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return DEFAULT_BACKGROUND_JOB_MAX_RETRIES
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Validates an enqueue eligibility timestamp.
|
|
69
|
+
* @param {number | undefined} scheduledAtMs - Requested timestamp.
|
|
70
|
+
* @param {number} defaultScheduledAtMs - Default timestamp.
|
|
71
|
+
* @returns {number} - Eligibility timestamp.
|
|
72
|
+
*/
|
|
73
|
+
export function normalizeBackgroundJobScheduledAtMs(scheduledAtMs, defaultScheduledAtMs) {
|
|
74
|
+
if (scheduledAtMs === undefined) return defaultScheduledAtMs
|
|
75
|
+
if (Number.isSafeInteger(scheduledAtMs) && scheduledAtMs >= 0) return scheduledAtMs
|
|
76
|
+
|
|
77
|
+
throw VelociousError.safe("background job scheduledAtMs must be a non-negative safe integer")
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Validates a reschedule delay and resolves it at persistence time.
|
|
82
|
+
* @param {number} delayMs - Requested delay.
|
|
83
|
+
* @param {number} nowMs - Persistence timestamp.
|
|
84
|
+
* @returns {number} - New eligibility timestamp.
|
|
85
|
+
*/
|
|
86
|
+
export function rescheduledBackgroundJobAtMs(delayMs, nowMs) {
|
|
87
|
+
if (!Number.isSafeInteger(delayMs) || delayMs < 0) {
|
|
88
|
+
throw VelociousError.safe("background job reschedule delayMs must be a non-negative safe integer")
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const scheduledAtMs = nowMs + delayMs
|
|
92
|
+
|
|
93
|
+
if (!Number.isSafeInteger(scheduledAtMs)) {
|
|
94
|
+
throw VelociousError.safe("background job reschedule scheduledAtMs must be a safe integer")
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return scheduledAtMs
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Returns the shared failure backoff.
|
|
102
|
+
* @param {number} retryCount - One-based failed attempt count.
|
|
103
|
+
* @returns {number} - Backoff in milliseconds.
|
|
104
|
+
*/
|
|
105
|
+
export function retryDelayMs(retryCount) {
|
|
106
|
+
const scheduleSeconds = [10, 60, 600, 3600]
|
|
107
|
+
|
|
108
|
+
if (retryCount <= scheduleSeconds.length) return scheduleSeconds[retryCount - 1] * 1000
|
|
109
|
+
|
|
110
|
+
return (retryCount - 3) * 60 * 60 * 1000
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Resolves explicit or queue-derived concurrency.
|
|
115
|
+
* @param {object} args - Resolution arguments.
|
|
116
|
+
* @param {import("./types.js").BackgroundJobOptions} args.options - Job options.
|
|
117
|
+
* @param {string} args.queue - Normalized queue.
|
|
118
|
+
* @param {Record<string, {maxConcurrent?: number, priority?: number}>} args.queues - Queue configuration.
|
|
119
|
+
* @returns {import("./types.js").ResolvedBackgroundJobConcurrency | null} - Concurrency contract.
|
|
120
|
+
*/
|
|
121
|
+
export function normalizeBackgroundJobConcurrency({options = {}, queue, queues}) {
|
|
122
|
+
const key = options.concurrencyKey
|
|
123
|
+
const cap = options.maxConcurrency
|
|
124
|
+
|
|
125
|
+
if (key !== undefined || cap !== undefined) {
|
|
126
|
+
if (typeof key !== "string" || key.length === 0 || !Number.isInteger(cap) || Number(cap) <= 0) {
|
|
127
|
+
throw new Error("background job concurrencyKey and maxConcurrency must be paired; concurrencyKey must be non-empty and maxConcurrency must be a positive integer")
|
|
128
|
+
}
|
|
129
|
+
if (key.startsWith(QUEUE_CONCURRENCY_KEY_PREFIX)) {
|
|
130
|
+
throw new Error(`background job concurrencyKey must not start with the reserved "${QUEUE_CONCURRENCY_KEY_PREFIX}" prefix, which is reserved for queue-derived concurrency caps`)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {concurrencyKey: key, maxConcurrency: Number(cap), queueDerived: false}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const queueCap = queues[queue]?.maxConcurrent
|
|
137
|
+
|
|
138
|
+
if (!Number.isInteger(queueCap) || Number(queueCap) <= 0) return null
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
concurrencyKey: `${QUEUE_CONCURRENCY_KEY_PREFIX}${queue}`,
|
|
142
|
+
maxConcurrency: Number(queueCap),
|
|
143
|
+
queueDerived: true
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import BackgroundJobsAdapter from "./adapter.js"
|
|
4
|
+
import LocalBackgroundJobsDispatcher from "./local-dispatcher.js"
|
|
5
|
+
import LocalBackgroundJobRegistry from "./local-job-registry.js"
|
|
6
|
+
import LocalBackgroundJobsStore, {localBackgroundJobsClock} from "./local-store.js"
|
|
7
|
+
|
|
8
|
+
/** Durable local SQLite adapter with an owned in-process dispatcher. */
|
|
9
|
+
export default class LocalBackgroundJobsAdapter extends BackgroundJobsAdapter {
|
|
10
|
+
/**
|
|
11
|
+
* Creates a local adapter for one configuration and database.
|
|
12
|
+
* @param {object} args - Adapter options.
|
|
13
|
+
* @param {import("../configuration.js").default} args.configuration - Owning configuration.
|
|
14
|
+
* @param {import("./types.js").LocalBackgroundJobsClock} [args.clock] - Injectable clock.
|
|
15
|
+
* @param {string} [args.databaseIdentifier] - Local database identifier.
|
|
16
|
+
*/
|
|
17
|
+
constructor({configuration, clock = localBackgroundJobsClock(), databaseIdentifier}) {
|
|
18
|
+
super()
|
|
19
|
+
this.clock = clock
|
|
20
|
+
this.configuration = configuration
|
|
21
|
+
this.registry = new LocalBackgroundJobRegistry({jobClasses: configuration.getBackgroundJobClasses()})
|
|
22
|
+
this.store = new LocalBackgroundJobsStore({
|
|
23
|
+
clock,
|
|
24
|
+
configuration,
|
|
25
|
+
databaseIdentifier,
|
|
26
|
+
onCommittedEnqueue: () => this.dispatcher.wake()
|
|
27
|
+
})
|
|
28
|
+
this.dispatcher = new LocalBackgroundJobsDispatcher({clock, configuration, registry: this.registry, store: this.store})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Ensures that local persistence and dispatch are ready.
|
|
33
|
+
* @returns {Promise<void>} - Resolves when local dispatch is ready.
|
|
34
|
+
*/
|
|
35
|
+
async ensureReady() { await this.dispatcher.start() }
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Stops local dispatch gracefully.
|
|
39
|
+
* @returns {Promise<void>} - Resolves after graceful local shutdown.
|
|
40
|
+
*/
|
|
41
|
+
async close() {
|
|
42
|
+
await this.dispatcher.stop()
|
|
43
|
+
this.store.resetReadiness()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Reports local dispatcher health.
|
|
48
|
+
* @returns {Promise<import("./types.js").BackgroundJobsHealth>} - Local adapter health.
|
|
49
|
+
*/
|
|
50
|
+
async health() { return {ready: this.dispatcher.isReady()} }
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Reconciles configuration-derived queue concurrency caps.
|
|
54
|
+
* @returns {Promise<void>} - Resolves after queue cap reconciliation.
|
|
55
|
+
*/
|
|
56
|
+
async reconcileQueueConcurrency() { await this.store.reconcileQueueConcurrency() }
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Enqueues one statically registered local job.
|
|
60
|
+
* @param {{jobName: string, args: Array<ReturnType<typeof JSON.parse>>, options?: import("./types.js").BackgroundJobOptions}} args - Enqueue request.
|
|
61
|
+
* @returns {Promise<string>} - Durable local job id.
|
|
62
|
+
*/
|
|
63
|
+
async enqueue(args) {
|
|
64
|
+
await this.ensureReady()
|
|
65
|
+
this.registry.resolve(args.jobName)
|
|
66
|
+
return await this.store.enqueue(args)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Rejects stable-key cancellation, which is outside the local adapter contract.
|
|
71
|
+
* @param {string} _scheduleKey - Unsupported stable key.
|
|
72
|
+
* @returns {Promise<import("./types.js").BackgroundJobCancellationResult>} - Never resolves.
|
|
73
|
+
*/
|
|
74
|
+
async cancelScheduled(_scheduleKey) { throw new Error("cancelScheduled is not supported by the local background-jobs adapter") }
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Rejects stable-key replacement, which is outside the local adapter contract.
|
|
78
|
+
* @param {{scheduleKey: string, jobName: string, args: Array<ReturnType<typeof JSON.parse>>, options?: import("./types.js").BackgroundJobOptions}} _args - Unsupported request.
|
|
79
|
+
* @returns {Promise<import("./types.js").BackgroundJobReplacementResult>} - Never resolves.
|
|
80
|
+
*/
|
|
81
|
+
async replaceScheduled(_args) { throw new Error("replaceScheduled is not supported by the local background-jobs adapter") }
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Finds the next eligible local job.
|
|
85
|
+
* @returns {Promise<import("./types.js").BackgroundJobRow | null>} - Next eligible job.
|
|
86
|
+
*/
|
|
87
|
+
async nextAvailableJob() { return await this.store.nextAvailableJob() }
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Finds the next future local job.
|
|
91
|
+
* @returns {Promise<import("./types.js").BackgroundJobRow | null>} - Next future job.
|
|
92
|
+
*/
|
|
93
|
+
async nextScheduledJob() { return await this.store.nextScheduledJob() }
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Finds a local job by id.
|
|
97
|
+
* @param {string} jobId - Job id.
|
|
98
|
+
* @returns {Promise<import("./types.js").BackgroundJobRow | null>} - Persisted job.
|
|
99
|
+
*/
|
|
100
|
+
async getJob(jobId) { return await this.store.getJob(jobId) }
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Lists local jobs in insertion order.
|
|
104
|
+
* @returns {Promise<import("./types.js").BackgroundJobRow[]>} - Local jobs.
|
|
105
|
+
*/
|
|
106
|
+
async listJobs() { return await this.store.listJobs() }
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Claims one queued local job.
|
|
110
|
+
* @param {{jobId: string, workerId?: string}} args - Claim request.
|
|
111
|
+
* @returns {Promise<import("./types.js").BackgroundJobHandoff | null>} - Handoff.
|
|
112
|
+
*/
|
|
113
|
+
async markHandedOff(args) { return await this.store.markHandedOff(args) }
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Finds active local handoffs owned by one worker.
|
|
117
|
+
* @param {{workerId: string}} args - Worker identity.
|
|
118
|
+
* @returns {Promise<Array<{jobId: string, handoffId: string}>>} - Active worker handoffs.
|
|
119
|
+
*/
|
|
120
|
+
async handedOffJobsForWorker(args) { return await this.store.handedOffJobsForWorker(args) }
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Returns an exact active local handoff to the queue.
|
|
124
|
+
* @param {{jobId: string, handoffId: string}} args - Handoff release.
|
|
125
|
+
* @returns {Promise<void>} - Resolves after the fenced release.
|
|
126
|
+
*/
|
|
127
|
+
async markReturnedToQueue(args) { await this.store.markReturnedToQueue(args) }
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Acknowledges successful local job completion.
|
|
131
|
+
* @param {{jobId: string, handoffId?: string}} args - Completion report.
|
|
132
|
+
* @returns {Promise<boolean>} - Whether accepted.
|
|
133
|
+
*/
|
|
134
|
+
async markCompleted(args) { return await this.store.markCompleted(args) }
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Acknowledges an explicit local reschedule.
|
|
138
|
+
* @param {{jobId: string, delayMs: number, handoffId?: string}} args - Reschedule report.
|
|
139
|
+
* @returns {Promise<boolean>} - Whether accepted.
|
|
140
|
+
*/
|
|
141
|
+
async markRescheduled(args) { return await this.store.markRescheduled(args) }
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Acknowledges a failed local performance.
|
|
145
|
+
* @param {{jobId: string, error: ReturnType<typeof JSON.parse>, handoffId?: string}} args - Failure report.
|
|
146
|
+
* @returns {Promise<import("./types.js").BackgroundJobRow | null>} - Transition.
|
|
147
|
+
*/
|
|
148
|
+
async markFailed(args) { return await this.store.markFailed(args) }
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Coalesces a dispatcher wake.
|
|
152
|
+
* @returns {void} - No return value.
|
|
153
|
+
*/
|
|
154
|
+
wake() { this.dispatcher.wake() }
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Waits until current local work has been acknowledged.
|
|
158
|
+
* @returns {Promise<void>} - Resolves after all current work is acknowledged.
|
|
159
|
+
*/
|
|
160
|
+
async waitForIdle() { await this.dispatcher.waitForIdle() }
|
|
161
|
+
}
|