velocious 1.0.598 → 1.0.600

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.
Files changed (90) hide show
  1. package/README.md +12 -1
  2. package/build/background-jobs/adapter-client.js +45 -0
  3. package/build/background-jobs/adapter.js +139 -0
  4. package/build/background-jobs/job-registry.js +1 -1
  5. package/build/background-jobs/job.js +20 -129
  6. package/build/background-jobs/main.js +71 -28
  7. package/build/background-jobs/perform-job.js +23 -0
  8. package/build/background-jobs/platform-job.js +156 -0
  9. package/build/background-jobs/runtime.js +156 -0
  10. package/build/background-jobs/sql-adapter.js +20 -0
  11. package/build/background-jobs/store.js +3 -1
  12. package/build/background-jobs/types.js +10 -0
  13. package/build/background-jobs/web/controller.js +5 -2
  14. package/build/background-jobs/worker.js +6 -8
  15. package/build/configuration-types.js +5 -0
  16. package/build/configuration.js +217 -40
  17. package/build/environment-handlers/base.js +20 -0
  18. package/build/environment-handlers/node.js +27 -20
  19. package/build/jobs/prune-terminal-background-jobs.js +2 -3
  20. package/build/src/background-jobs/adapter-client.d.ts +41 -0
  21. package/build/src/background-jobs/adapter-client.d.ts.map +1 -0
  22. package/build/src/background-jobs/adapter-client.js +39 -0
  23. package/build/src/background-jobs/adapter.d.ts +165 -0
  24. package/build/src/background-jobs/adapter.d.ts.map +1 -0
  25. package/build/src/background-jobs/adapter.js +121 -0
  26. package/build/src/background-jobs/job-registry.d.ts +1 -1
  27. package/build/src/background-jobs/job-registry.d.ts.map +1 -1
  28. package/build/src/background-jobs/job-registry.js +2 -2
  29. package/build/src/background-jobs/job.d.ts +6 -69
  30. package/build/src/background-jobs/job.d.ts.map +1 -1
  31. package/build/src/background-jobs/job.js +17 -116
  32. package/build/src/background-jobs/main.d.ts +13 -3
  33. package/build/src/background-jobs/main.d.ts.map +1 -1
  34. package/build/src/background-jobs/main.js +66 -30
  35. package/build/src/background-jobs/perform-job.d.ts +16 -0
  36. package/build/src/background-jobs/perform-job.d.ts.map +1 -0
  37. package/build/src/background-jobs/perform-job.js +22 -0
  38. package/build/src/background-jobs/platform-job.d.ts +110 -0
  39. package/build/src/background-jobs/platform-job.d.ts.map +1 -0
  40. package/build/src/background-jobs/platform-job.js +138 -0
  41. package/build/src/background-jobs/runtime.d.ts +78 -0
  42. package/build/src/background-jobs/runtime.d.ts.map +1 -0
  43. package/build/src/background-jobs/runtime.js +132 -0
  44. package/build/src/background-jobs/sql-adapter.d.ts +13 -0
  45. package/build/src/background-jobs/sql-adapter.d.ts.map +1 -0
  46. package/build/src/background-jobs/sql-adapter.js +18 -0
  47. package/build/src/background-jobs/store.d.ts +2 -1
  48. package/build/src/background-jobs/store.d.ts.map +1 -1
  49. package/build/src/background-jobs/store.js +4 -2
  50. package/build/src/background-jobs/types.d.ts +41 -0
  51. package/build/src/background-jobs/types.d.ts.map +1 -1
  52. package/build/src/background-jobs/types.js +11 -1
  53. package/build/src/background-jobs/web/controller.d.ts.map +1 -1
  54. package/build/src/background-jobs/web/controller.js +5 -3
  55. package/build/src/background-jobs/worker.d.ts.map +1 -1
  56. package/build/src/background-jobs/worker.js +7 -8
  57. package/build/src/configuration-types.d.ts +16 -0
  58. package/build/src/configuration-types.d.ts.map +1 -1
  59. package/build/src/configuration-types.js +5 -1
  60. package/build/src/configuration.d.ts +51 -2
  61. package/build/src/configuration.d.ts.map +1 -1
  62. package/build/src/configuration.js +202 -39
  63. package/build/src/environment-handlers/base.d.ts +17 -0
  64. package/build/src/environment-handlers/base.d.ts.map +1 -1
  65. package/build/src/environment-handlers/base.js +19 -1
  66. package/build/src/environment-handlers/node.d.ts +18 -0
  67. package/build/src/environment-handlers/node.d.ts.map +1 -1
  68. package/build/src/environment-handlers/node.js +25 -20
  69. package/build/src/jobs/prune-terminal-background-jobs.d.ts.map +1 -1
  70. package/build/src/jobs/prune-terminal-background-jobs.js +3 -4
  71. package/build/tsconfig.tsbuildinfo +1 -1
  72. package/package.json +1 -1
  73. package/src/background-jobs/adapter-client.js +45 -0
  74. package/src/background-jobs/adapter.js +139 -0
  75. package/src/background-jobs/job-registry.js +1 -1
  76. package/src/background-jobs/job.js +20 -129
  77. package/src/background-jobs/main.js +71 -28
  78. package/src/background-jobs/perform-job.js +23 -0
  79. package/src/background-jobs/platform-job.js +156 -0
  80. package/src/background-jobs/runtime.js +156 -0
  81. package/src/background-jobs/sql-adapter.js +20 -0
  82. package/src/background-jobs/store.js +3 -1
  83. package/src/background-jobs/types.js +10 -0
  84. package/src/background-jobs/web/controller.js +5 -2
  85. package/src/background-jobs/worker.js +6 -8
  86. package/src/configuration-types.js +5 -0
  87. package/src/configuration.js +217 -40
  88. package/src/environment-handlers/base.js +20 -0
  89. package/src/environment-handlers/node.js +27 -20
  90. package/src/jobs/prune-terminal-background-jobs.js +2 -3
@@ -0,0 +1,156 @@
1
+ // @ts-check
2
+
3
+ import BackgroundJobRescheduleSignal from "./reschedule-signal.js"
4
+ import {cancelScheduledBackgroundJob, enqueueBackgroundJob, replaceScheduledBackgroundJob} from "./runtime.js"
5
+
6
+ /**
7
+ * Base class for background jobs.
8
+ *
9
+ * `TArgs` is the tuple of arguments the subclass's `perform` accepts, so a job that
10
+ * needs arguments declares them as required and typed — for example
11
+ * `class RunBuildJob extends VelociousJob<[string]>` with `async perform(buildId)`.
12
+ * The default empty tuple keeps argument-less jobs (`extends VelociousJob`,
13
+ * `async perform()`) working unchanged.
14
+ * @template {Array<ReturnType<typeof JSON.parse>>} [TArgs=[]]
15
+ */
16
+ export default class VelociousJob {
17
+ /**
18
+ * Database identifiers checked out while this job performs. Set an explicit
19
+ * list to avoid holding unrelated configured database connections, or `[]`
20
+ * when the job establishes any connections it needs itself. Left undefined,
21
+ * jobs retain the existing behavior of checking out every active database.
22
+ * @type {string[] | undefined}
23
+ */
24
+ static databaseIdentifiers = undefined
25
+
26
+ /**
27
+ * Queue this job class runs on. Subclasses set e.g. `static queue = "builds"`
28
+ * to route onto a queue with its own cluster-wide concurrency cap (configured
29
+ * via `backgroundJobs.queues`). The `{queue}` enqueue option overrides it.
30
+ * Left undefined, jobs run on the `"default"` queue.
31
+ * @type {string | undefined}
32
+ */
33
+ static queue = undefined
34
+
35
+ /**
36
+ * Optional process title shown for the runner while this job executes.
37
+ * Velocious sets `process.title` to this for the duration of the job — so
38
+ * `ps`/`top`/`htop` identify what a runner is doing — and restores the
39
+ * runner's base title when the job finishes. Left undefined, the runner falls
40
+ * back to `velocious job-runner: <JobName>`. Set e.g.
41
+ * `static processTitle = "velocious media transcoder"` to give a job a
42
+ * custom, human-readable title.
43
+ * @type {string | undefined}
44
+ */
45
+ static processTitle = undefined
46
+
47
+ /**
48
+ * Stops this performance and reschedules the same logical job row. This is
49
+ * normal control flow: it does not count as a failure or consume a retry.
50
+ * @param {number} delayMs - Non-negative safe-integer delay in milliseconds.
51
+ * @returns {never} - This method never returns.
52
+ */
53
+ rescheduleIn(delayMs) {
54
+ if (!Number.isSafeInteger(delayMs) || delayMs < 0) {
55
+ throw new TypeError("background job reschedule delayMs must be a non-negative safe integer")
56
+ }
57
+
58
+ throw new BackgroundJobRescheduleSignal(delayMs)
59
+ }
60
+
61
+ /**
62
+ * Runs job name.
63
+ * @returns {string} - Job name.
64
+ */
65
+ static jobName() {
66
+ return this.name
67
+ }
68
+
69
+ /**
70
+ * Folds this job class's static `queue` into the enqueue options unless the
71
+ * caller already specified one.
72
+ * @param {import("./types.js").BackgroundJobOptions | undefined} options - Job options.
73
+ * @returns {import("./types.js").BackgroundJobOptions} - Options including the resolved queue.
74
+ */
75
+ static _withQueue(options) {
76
+ const merged = options ? {...options} : {}
77
+
78
+ if (merged.queue === undefined && typeof this.queue === "string" && this.queue.length > 0) {
79
+ merged.queue = this.queue
80
+ }
81
+
82
+ return merged
83
+ }
84
+
85
+ /**
86
+ * Runs perform later.
87
+ * @param {...ReturnType<typeof JSON.parse>} args - Job args.
88
+ * @returns {Promise<string>} - Job id.
89
+ */
90
+ static async performLater(...args) {
91
+ const {jobArgs, jobOptions} = this._splitArgsAndOptions(args)
92
+ return await enqueueBackgroundJob({JobClass: this, jobArgs, jobOptions})
93
+ }
94
+
95
+ /**
96
+ * Runs perform later with options.
97
+ * @param {object} args - Options.
98
+ * @param {Array<ReturnType<typeof JSON.parse>>} args.args - Job args.
99
+ * @param {import("./types.js").BackgroundJobOptions} [args.options] - Job options.
100
+ * @returns {Promise<string>} - Job id.
101
+ */
102
+ static async performLaterWithOptions({args, options}) {
103
+ return await enqueueBackgroundJob({JobClass: this, jobArgs: args, jobOptions: options})
104
+ }
105
+
106
+ /**
107
+ * Atomically replaces this job class's queued owner for a stable schedule key.
108
+ * @param {object} args - Options.
109
+ * @param {string} args.scheduleKey - Stable logical schedule key.
110
+ * @param {Array<ReturnType<typeof JSON.parse>>} args.args - Job args.
111
+ * @param {import("./types.js").BackgroundJobOptions} [args.options] - Job options.
112
+ * @returns {Promise<import("./types.js").BackgroundJobReplacementResult>} - Replacement result.
113
+ */
114
+ static async replaceScheduled({scheduleKey, args, options}) {
115
+ return await replaceScheduledBackgroundJob({JobClass: this, scheduleKey, jobArgs: args, jobOptions: options})
116
+ }
117
+
118
+ /**
119
+ * Cancels or detaches the current owner of a stable schedule key.
120
+ * @param {string} scheduleKey - Stable logical schedule key.
121
+ * @returns {Promise<import("./types.js").BackgroundJobCancellationResult>} - Cancellation result.
122
+ */
123
+ static async cancelScheduled(scheduleKey) {
124
+ return await cancelScheduledBackgroundJob(scheduleKey)
125
+ }
126
+
127
+ /**
128
+ * Runs split args and options.
129
+ * @param {Array<ReturnType<typeof JSON.parse>>} args - Job args.
130
+ * @returns {{jobArgs: Array<ReturnType<typeof JSON.parse>>, jobOptions: import("./types.js").BackgroundJobOptions}} - Split args and options.
131
+ */
132
+ static _splitArgsAndOptions(args) {
133
+ if (args.length === 0) {
134
+ return {jobArgs: [], jobOptions: {}}
135
+ }
136
+
137
+ const lastArg = args[args.length - 1]
138
+ const isOptionsArg = lastArg && typeof lastArg === "object" && !Array.isArray(lastArg) && "jobOptions" in lastArg
139
+
140
+ if (isOptionsArg) {
141
+ const {jobOptions} = /** @type {{jobOptions: import("./types.js").BackgroundJobOptions}} */ (lastArg)
142
+ return {jobArgs: args.slice(0, -1), jobOptions: jobOptions || {}}
143
+ }
144
+
145
+ return {jobArgs: args, jobOptions: {}}
146
+ }
147
+
148
+ /**
149
+ * Override in subclasses.
150
+ * @param {TArgs} _args - Job args (the tuple this job class was parameterized with).
151
+ * @returns {Promise<void>} - Resolves when complete.
152
+ */
153
+ async perform(..._args) {
154
+ throw new Error("perform not implemented")
155
+ }
156
+ }
@@ -0,0 +1,156 @@
1
+ // @ts-check
2
+
3
+ import {currentConfiguration} from "../current-configuration.js"
4
+ import performBackgroundJob from "./perform-job.js"
5
+ import BackgroundJobRescheduleSignal from "./reschedule-signal.js"
6
+
7
+ let inlinePerformanceSequence = 0
8
+
9
+ /**
10
+ * Rejects options whose semantics require durable queue state.
11
+ * @param {import("./types.js").BackgroundJobOptions | undefined} options - Requested options.
12
+ * @returns {void}
13
+ */
14
+ function validateInlineOptions(options) {
15
+ const optionNames = Object.keys(options || {})
16
+
17
+ if (optionNames.length > 0) {
18
+ throw new Error(`Background job option ${optionNames[0]} is not supported in inline mode`)
19
+ }
20
+ }
21
+
22
+ /**
23
+ * Builds an ephemeral inline performance id.
24
+ * @returns {string} - Performance id.
25
+ */
26
+ function inlineJobId() {
27
+ inlinePerformanceSequence++
28
+ return `inline-${Date.now()}-${inlinePerformanceSequence}`
29
+ }
30
+
31
+ /**
32
+ * Enqueues durably in background mode or performs immediately in inline mode.
33
+ * @param {object} args - Enqueue request.
34
+ * @param {typeof import("./platform-job.js").default} args.JobClass - Job class.
35
+ * @param {Array<ReturnType<typeof JSON.parse>>} args.jobArgs - Job arguments.
36
+ * @param {import("./types.js").BackgroundJobOptions | undefined} args.jobOptions - Job options.
37
+ * @returns {Promise<string>} - Durable job id or ephemeral inline performance id.
38
+ */
39
+ export async function enqueueBackgroundJob({JobClass, jobArgs, jobOptions}) {
40
+ const configuration = currentConfiguration()
41
+
42
+ return await enqueueBackgroundJobForConfiguration({configuration, JobClass, jobArgs, jobOptions})
43
+ }
44
+
45
+ /**
46
+ * Enqueues using an explicitly resolved configuration.
47
+ * @param {object} args - Enqueue request.
48
+ * @param {import("../configuration.js").default} args.configuration - Configuration.
49
+ * @param {typeof import("./platform-job.js").default} args.JobClass - Job class.
50
+ * @param {Array<ReturnType<typeof JSON.parse>>} args.jobArgs - Job arguments.
51
+ * @param {import("./types.js").BackgroundJobOptions | undefined} args.jobOptions - Job options.
52
+ * @returns {Promise<string>} - Durable job id or ephemeral inline performance id.
53
+ */
54
+ export async function enqueueBackgroundJobForConfiguration({configuration, JobClass, jobArgs, jobOptions}) {
55
+
56
+ if (configuration.getBackgroundJobsConfig().mode === "inline") {
57
+ validateInlineOptions(jobOptions)
58
+ configuration.setCurrent()
59
+ await configuration.initialize({type: "background-jobs-inline"})
60
+
61
+ try {
62
+ await performBackgroundJob({
63
+ configuration,
64
+ JobClass,
65
+ jobArgs,
66
+ name: `Background job inline mode: ${JobClass.jobName()}`
67
+ })
68
+ } catch (error) {
69
+ if (error instanceof BackgroundJobRescheduleSignal) {
70
+ throw new Error("rescheduleIn is not supported in inline mode", {cause: error})
71
+ }
72
+
73
+ throw error
74
+ }
75
+
76
+ return inlineJobId()
77
+ }
78
+
79
+ const client = configuration.getEnvironmentHandler().backgroundJobsClient({configuration})
80
+
81
+ return await client.enqueue({
82
+ jobName: JobClass.jobName(),
83
+ args: jobArgs,
84
+ options: JobClass._withQueue(jobOptions)
85
+ })
86
+ }
87
+
88
+ /**
89
+ * Replaces a stable durable schedule in background mode.
90
+ * @param {object} args - Replacement request.
91
+ * @param {typeof import("./platform-job.js").default} args.JobClass - Job class.
92
+ * @param {string} args.scheduleKey - Stable schedule key.
93
+ * @param {Array<ReturnType<typeof JSON.parse>>} args.jobArgs - Job arguments.
94
+ * @param {import("./types.js").BackgroundJobOptions | undefined} args.jobOptions - Job options.
95
+ * @returns {Promise<import("./types.js").BackgroundJobReplacementResult>} - Replacement result.
96
+ */
97
+ export async function replaceScheduledBackgroundJob({JobClass, scheduleKey, jobArgs, jobOptions}) {
98
+ const configuration = currentConfiguration()
99
+
100
+ return await replaceScheduledBackgroundJobForConfiguration({configuration, JobClass, scheduleKey, jobArgs, jobOptions})
101
+ }
102
+
103
+ /**
104
+ * Replaces a stable schedule using an explicitly resolved configuration.
105
+ * @param {object} args - Replacement request.
106
+ * @param {import("../configuration.js").default} args.configuration - Configuration.
107
+ * @param {typeof import("./platform-job.js").default} args.JobClass - Job class.
108
+ * @param {string} args.scheduleKey - Stable schedule key.
109
+ * @param {Array<ReturnType<typeof JSON.parse>>} args.jobArgs - Job arguments.
110
+ * @param {import("./types.js").BackgroundJobOptions | undefined} args.jobOptions - Job options.
111
+ * @returns {Promise<import("./types.js").BackgroundJobReplacementResult>} - Replacement result.
112
+ */
113
+ export async function replaceScheduledBackgroundJobForConfiguration({configuration, JobClass, scheduleKey, jobArgs, jobOptions}) {
114
+
115
+ if (configuration.getBackgroundJobsConfig().mode === "inline") {
116
+ throw new Error("replaceScheduled is not supported in inline mode")
117
+ }
118
+
119
+ const client = configuration.getEnvironmentHandler().backgroundJobsClient({configuration})
120
+
121
+ return await client.replaceScheduled({
122
+ scheduleKey,
123
+ jobName: JobClass.jobName(),
124
+ args: jobArgs,
125
+ options: JobClass._withQueue(jobOptions)
126
+ })
127
+ }
128
+
129
+ /**
130
+ * Cancels a stable durable schedule in background mode.
131
+ * @param {string} scheduleKey - Stable schedule key.
132
+ * @returns {Promise<import("./types.js").BackgroundJobCancellationResult>} - Cancellation result.
133
+ */
134
+ export async function cancelScheduledBackgroundJob(scheduleKey) {
135
+ const configuration = currentConfiguration()
136
+
137
+ return await cancelScheduledBackgroundJobForConfiguration({configuration, scheduleKey})
138
+ }
139
+
140
+ /**
141
+ * Cancels a stable schedule using an explicitly resolved configuration.
142
+ * @param {object} args - Cancellation request.
143
+ * @param {import("../configuration.js").default} args.configuration - Configuration.
144
+ * @param {string} args.scheduleKey - Stable logical schedule key.
145
+ * @returns {Promise<import("./types.js").BackgroundJobCancellationResult>} - Cancellation result.
146
+ */
147
+ export async function cancelScheduledBackgroundJobForConfiguration({configuration, scheduleKey}) {
148
+
149
+ if (configuration.getBackgroundJobsConfig().mode === "inline") {
150
+ throw new Error("cancelScheduled is not supported in inline mode")
151
+ }
152
+
153
+ const client = configuration.getEnvironmentHandler().backgroundJobsClient({configuration})
154
+
155
+ return await client.cancelScheduled({scheduleKey})
156
+ }
@@ -0,0 +1,20 @@
1
+ // @ts-check
2
+
3
+ import BackgroundJobsStore from "./store.js"
4
+
5
+ /** Built-in SQL adapter preserving the existing durable store implementation. */
6
+ export default class SqlBackgroundJobsAdapter extends BackgroundJobsStore {
7
+ /**
8
+ * Ensures the built-in SQL schema during migration.
9
+ * @param {{dbs: Record<string, import("../database/drivers/base.js").default>}} args - Migrated databases.
10
+ * @returns {Promise<void>} - Resolves when the SQL schema is present.
11
+ */
12
+ async ensureFrameworkSchema({dbs}) {
13
+ const databaseIdentifier = this.getDatabaseIdentifier() || "default"
14
+ const frameworkDb = dbs[databaseIdentifier]
15
+
16
+ if (!frameworkDb) return
17
+
18
+ await this.ensureSchema(frameworkDb)
19
+ }
20
+ }
@@ -1,6 +1,7 @@
1
1
  // @ts-check
2
2
 
3
3
  import {createHash, randomUUID} from "crypto"
4
+ import BackgroundJobsAdapter from "./adapter.js"
4
5
  import Logger from "../logger.js"
5
6
  import TableData from "../database/table-data/index.js"
6
7
  import VelociousError from "../velocious-error.js"
@@ -100,7 +101,7 @@ const schemaApplyChains = new Map()
100
101
  /** @type {Map<string, Promise<void>>} */
101
102
  const transactionMutationChains = new Map()
102
103
 
103
- export default class BackgroundJobsStore {
104
+ export default class BackgroundJobsStore extends BackgroundJobsAdapter {
104
105
  /**
105
106
  * Runs constructor.
106
107
  * @param {object} args - Options.
@@ -108,6 +109,7 @@ export default class BackgroundJobsStore {
108
109
  * @param {string} [args.databaseIdentifier] - Database identifier.
109
110
  */
110
111
  constructor({configuration, databaseIdentifier}) {
112
+ super()
111
113
  this.configuration = configuration
112
114
  this.databaseIdentifier = databaseIdentifier
113
115
  this.logger = new Logger(this)
@@ -3,6 +3,16 @@
3
3
  /**
4
4
  * @typedef {"inline" | "forked" | "pooled" | "spawned"} BackgroundJobExecutionMode
5
5
  */
6
+ /**
7
+ * @typedef {object} BackgroundJobsHealth
8
+ * @property {boolean} ready - Whether the adapter can accept and process work.
9
+ */
10
+ /**
11
+ * @typedef {object} BackgroundJobsProducer
12
+ * @property {(args: {jobName: string, args: Array<ReturnType<typeof JSON.parse>>, options?: BackgroundJobOptions}) => Promise<string>} enqueue - Enqueues a job.
13
+ * @property {(args: {scheduleKey: string, jobName: string, args: Array<ReturnType<typeof JSON.parse>>, options?: BackgroundJobOptions}) => Promise<BackgroundJobReplacementResult>} replaceScheduled - Replaces a stable schedule.
14
+ * @property {(args: {scheduleKey: string}) => Promise<BackgroundJobCancellationResult>} cancelScheduled - Cancels a stable schedule.
15
+ */
6
16
  /**
7
17
  * @typedef {object} BackgroundJobHandoff
8
18
  * @property {string} handoffId - Unique handoff lease id.
@@ -99,11 +99,14 @@ export default class VelociousBackgroundJobsWebController extends Controller {
99
99
  */
100
100
  async health() {
101
101
  await this._respond(async () => {
102
+ const health = await this.getConfiguration().backgroundJobsHealth()
103
+
102
104
  await this.render({json: {
103
105
  capabilities: {backgroundJobCountDeltas: 1},
104
- ok: true,
106
+ ok: health.ready,
107
+ ready: health.ready,
105
108
  service: "velocious-background-jobs"
106
- }})
109
+ }, status: health.ready ? 200 : 503})
107
110
  })
108
111
  }
109
112
 
@@ -10,6 +10,7 @@ import {randomUUID} from "crypto"
10
10
  import {fileURLToPath} from "node:url"
11
11
  import shutdownLifecycle from "../utils/shutdown-lifecycle.js"
12
12
  import BackgroundJobRescheduleSignal from "./reschedule-signal.js"
13
+ import performBackgroundJob from "./perform-job.js"
13
14
 
14
15
  /**
15
16
  * Per-forked-child timeout bookkeeping.
@@ -958,14 +959,11 @@ export default class BackgroundJobsWorker {
958
959
  const registry = new BackgroundJobRegistry({configuration})
959
960
  await registry.load()
960
961
  const JobClass = registry.getJobByName(payload.jobName)
961
- const jobInstance = new JobClass()
962
- /**
963
- * Perform.
964
- * @type {(...args: Array<ReturnType<typeof JSON.parse>>) => Promise<void>} */
965
- const perform = jobInstance.perform
966
-
967
- await configuration.withConnections({databaseIdentifiers: JobClass.databaseIdentifiers, name: `Background job worker inline: ${payload.jobName}`}, async () => {
968
- await perform.apply(jobInstance, payload.args || [])
962
+ await performBackgroundJob({
963
+ configuration,
964
+ JobClass,
965
+ jobArgs: payload.args || [],
966
+ name: `Background job worker inline: ${payload.jobName}`
969
967
  })
970
968
  }
971
969
 
@@ -156,8 +156,13 @@
156
156
  * `background_jobs` table (see `pollIntervalMs`).
157
157
  */
158
158
 
159
+ /** @typedef {"background" | "inline"} BackgroundJobsMode */
160
+ /** @typedef {(args: {configuration: import("./configuration.js").default}) => import("./background-jobs/adapter.js").default} BackgroundJobsAdapterFactory */
161
+
159
162
  /**
160
163
  * @typedef {object} BackgroundJobsConfiguration
164
+ * @property {import("./background-jobs/adapter.js").default | BackgroundJobsAdapterFactory} [adapter] - Adapter instance or synchronous factory. A factory creates one adapter per configuration lifecycle; the framework closes adapters it resolves.
165
+ * @property {BackgroundJobsMode} [mode] - `"background"` uses the configured adapter/transport and durable queue semantics; `"inline"` performs immediately without durable queue state. Defaults to `"background"`.
161
166
  * @property {string} [host] - Hostname for the background jobs main process.
162
167
  * @property {number} [port] - Port for the background jobs main process.
163
168
  * @property {string} [databaseIdentifier] - Database identifier used to store background jobs.