nmtjs 0.15.0-beta.2 → 0.15.0-beta.20
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/dist/cli.d.ts +2 -0
- package/dist/cli.js +3 -2
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +51 -0
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -0
- package/dist/entrypoints/cli.d.ts +1 -0
- package/dist/entrypoints/cli.js +1 -0
- package/dist/entrypoints/cli.js.map +1 -0
- package/dist/entrypoints/main.d.ts +5 -0
- package/dist/entrypoints/main.js +83 -15
- package/dist/entrypoints/main.js.map +1 -0
- package/dist/entrypoints/thread.d.ts +14 -0
- package/dist/entrypoints/thread.js +130 -24
- package/dist/entrypoints/thread.js.map +1 -0
- package/dist/entrypoints/worker.d.ts +3 -0
- package/dist/entrypoints/worker.js +4 -3
- package/dist/entrypoints/worker.js.map +1 -0
- package/dist/index.d.ts +69 -0
- package/dist/{_exports/index.js → index.js} +9 -5
- package/dist/index.js.map +1 -0
- package/dist/resolver.d.ts +2 -0
- package/dist/resolver.js +1 -0
- package/dist/resolver.js.map +1 -0
- package/dist/runtime/application/api/api.d.ts +49 -0
- package/dist/runtime/application/api/api.js +193 -0
- package/dist/runtime/application/api/api.js.map +1 -0
- package/dist/runtime/application/api/constants.d.ts +14 -0
- package/dist/runtime/application/api/constants.js +8 -0
- package/dist/runtime/application/api/constants.js.map +1 -0
- package/dist/runtime/application/api/filters.d.ts +14 -0
- package/dist/runtime/application/api/filters.js +11 -0
- package/dist/runtime/application/api/filters.js.map +1 -0
- package/dist/runtime/application/api/guards.d.ts +13 -0
- package/dist/runtime/application/api/guards.js +8 -0
- package/dist/runtime/application/api/guards.js.map +1 -0
- package/dist/runtime/application/api/index.d.ts +8 -0
- package/dist/runtime/application/api/index.js +9 -0
- package/dist/runtime/application/api/index.js.map +1 -0
- package/dist/runtime/application/api/middlewares.d.ts +14 -0
- package/dist/runtime/application/api/middlewares.js +12 -0
- package/dist/runtime/application/api/middlewares.js.map +1 -0
- package/dist/runtime/application/api/procedure.d.ts +67 -0
- package/dist/runtime/application/api/procedure.js +50 -0
- package/dist/runtime/application/api/procedure.js.map +1 -0
- package/dist/runtime/application/api/router.d.ts +71 -0
- package/dist/runtime/application/api/router.js +51 -0
- package/dist/runtime/application/api/router.js.map +1 -0
- package/dist/runtime/application/api/types.d.ts +32 -0
- package/dist/runtime/application/api/types.js +2 -0
- package/dist/runtime/application/api/types.js.map +1 -0
- package/dist/runtime/application/config.d.ts +26 -0
- package/dist/runtime/application/config.js +21 -0
- package/dist/runtime/application/config.js.map +1 -0
- package/dist/runtime/application/constants.d.ts +2 -0
- package/dist/runtime/application/constants.js +2 -0
- package/dist/runtime/application/constants.js.map +1 -0
- package/dist/runtime/application/hook.d.ts +19 -0
- package/dist/runtime/application/hook.js +11 -0
- package/dist/runtime/application/hook.js.map +1 -0
- package/dist/runtime/application/hooks.d.ts +3 -0
- package/dist/runtime/application/hooks.js +4 -0
- package/dist/runtime/application/hooks.js.map +1 -0
- package/dist/runtime/application/index.d.ts +5 -0
- package/dist/runtime/application/index.js +6 -0
- package/dist/runtime/application/index.js.map +1 -0
- package/dist/runtime/constants.d.ts +8 -0
- package/dist/runtime/constants.js +5 -0
- package/dist/runtime/constants.js.map +1 -0
- package/dist/runtime/core/hooks.d.ts +4 -0
- package/dist/runtime/core/hooks.js +4 -0
- package/dist/runtime/core/hooks.js.map +1 -0
- package/dist/runtime/core/plugin.d.ts +8 -0
- package/dist/runtime/core/plugin.js +4 -0
- package/dist/runtime/core/plugin.js.map +1 -0
- package/dist/runtime/core/runtime.d.ts +27 -0
- package/dist/runtime/core/runtime.js +81 -0
- package/dist/runtime/core/runtime.js.map +1 -0
- package/dist/runtime/enums.d.ts +21 -0
- package/dist/runtime/enums.js +26 -0
- package/dist/runtime/enums.js.map +1 -0
- package/dist/runtime/index.d.ts +21 -0
- package/dist/runtime/index.js +22 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/injectables.d.ts +23 -0
- package/dist/runtime/injectables.js +20 -0
- package/dist/runtime/injectables.js.map +1 -0
- package/dist/runtime/jobs/job.d.ts +132 -0
- package/dist/runtime/jobs/job.js +68 -0
- package/dist/runtime/jobs/job.js.map +1 -0
- package/dist/runtime/jobs/manager.d.ts +103 -0
- package/dist/runtime/jobs/manager.js +200 -0
- package/dist/runtime/jobs/manager.js.map +1 -0
- package/dist/runtime/jobs/router.d.ts +251 -0
- package/dist/runtime/jobs/router.js +396 -0
- package/dist/runtime/jobs/router.js.map +1 -0
- package/dist/runtime/jobs/runner.d.ts +64 -0
- package/dist/runtime/jobs/runner.js +256 -0
- package/dist/runtime/jobs/runner.js.map +1 -0
- package/dist/runtime/jobs/step.d.ts +22 -0
- package/dist/runtime/jobs/step.js +18 -0
- package/dist/runtime/jobs/step.js.map +1 -0
- package/dist/runtime/jobs/ui.d.ts +3 -0
- package/dist/runtime/jobs/ui.js +17 -0
- package/dist/runtime/jobs/ui.js.map +1 -0
- package/dist/runtime/pubsub/manager.d.ts +48 -0
- package/dist/runtime/pubsub/manager.js +119 -0
- package/dist/runtime/pubsub/manager.js.map +1 -0
- package/dist/runtime/pubsub/redis.d.ts +16 -0
- package/dist/runtime/pubsub/redis.js +98 -0
- package/dist/runtime/pubsub/redis.js.map +1 -0
- package/dist/runtime/scheduler/index.d.ts +22 -0
- package/dist/runtime/scheduler/index.js +20 -0
- package/dist/runtime/scheduler/index.js.map +1 -0
- package/dist/runtime/server/applications.d.ts +52 -0
- package/dist/runtime/server/applications.js +133 -0
- package/dist/runtime/server/applications.js.map +1 -0
- package/dist/runtime/server/config.d.ts +121 -0
- package/dist/runtime/server/config.js +33 -0
- package/dist/runtime/server/config.js.map +1 -0
- package/dist/runtime/server/jobs.d.ts +41 -0
- package/dist/runtime/server/jobs.js +181 -0
- package/dist/runtime/server/jobs.js.map +1 -0
- package/dist/runtime/server/pool.d.ts +54 -0
- package/dist/runtime/server/pool.js +194 -0
- package/dist/runtime/server/pool.js.map +1 -0
- package/dist/runtime/server/proxy.d.ts +21 -0
- package/dist/runtime/server/proxy.js +79 -0
- package/dist/runtime/server/proxy.js.map +1 -0
- package/dist/runtime/server/server.d.ts +53 -0
- package/dist/runtime/server/server.js +90 -0
- package/dist/runtime/server/server.js.map +1 -0
- package/dist/runtime/store/index.d.ts +3 -0
- package/dist/runtime/store/index.js +23 -0
- package/dist/runtime/store/index.js.map +1 -0
- package/dist/runtime/types.d.ts +103 -0
- package/dist/runtime/types.js +2 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/runtime/workers/application.d.ts +47 -0
- package/dist/runtime/workers/application.js +162 -0
- package/dist/runtime/workers/application.js.map +1 -0
- package/dist/runtime/workers/base.d.ts +16 -0
- package/dist/runtime/workers/base.js +46 -0
- package/dist/runtime/workers/base.js.map +1 -0
- package/dist/runtime/workers/cli.d.ts +1 -0
- package/dist/runtime/workers/cli.js +2 -0
- package/dist/runtime/workers/cli.js.map +1 -0
- package/dist/runtime/workers/job.d.ts +20 -0
- package/dist/runtime/workers/job.js +172 -0
- package/dist/runtime/workers/job.js.map +1 -0
- package/dist/typings.d.ts +5 -0
- package/dist/typings.js +4 -3
- package/dist/typings.js.map +1 -0
- package/dist/vite/builder.d.ts +5 -0
- package/dist/vite/builder.js +5 -1
- package/dist/vite/builder.js.map +1 -0
- package/dist/vite/config.d.ts +28 -0
- package/dist/vite/config.js +1 -0
- package/dist/vite/config.js.map +1 -0
- package/dist/vite/plugins.d.ts +2 -0
- package/dist/vite/plugins.js +1 -0
- package/dist/vite/plugins.js.map +1 -0
- package/dist/vite/runners/worker.d.ts +4 -0
- package/dist/vite/runners/worker.js +1 -0
- package/dist/vite/runners/worker.js.map +1 -0
- package/dist/vite/server.d.ts +3 -0
- package/dist/vite/server.js +6 -1
- package/dist/vite/server.js.map +1 -0
- package/dist/vite/servers/main.d.ts +8 -0
- package/dist/vite/servers/main.js +1 -0
- package/dist/vite/servers/main.js.map +1 -0
- package/dist/vite/servers/worker.d.ts +11 -0
- package/dist/vite/servers/worker.js +28 -0
- package/dist/vite/servers/worker.js.map +1 -0
- package/package.json +31 -18
- package/src/cli.ts +144 -0
- package/src/config.ts +64 -0
- package/src/entrypoints/cli.ts +13 -0
- package/src/entrypoints/main.ts +200 -0
- package/src/entrypoints/thread.ts +184 -0
- package/src/entrypoints/worker.ts +48 -0
- package/src/index.ts +82 -0
- package/src/resolver.ts +16 -0
- package/src/runtime/application/api/api.ts +265 -0
- package/src/runtime/application/api/constants.ts +22 -0
- package/src/runtime/application/api/filters.ts +39 -0
- package/src/runtime/application/api/guards.ts +29 -0
- package/src/runtime/application/api/index.ts +8 -0
- package/src/runtime/application/api/middlewares.ts +37 -0
- package/src/runtime/application/api/procedure.ts +229 -0
- package/src/runtime/application/api/router.ts +193 -0
- package/src/runtime/application/api/types.ts +124 -0
- package/src/runtime/application/config.ts +69 -0
- package/src/runtime/application/constants.ts +4 -0
- package/src/runtime/application/hook.ts +51 -0
- package/src/runtime/application/hooks.ts +3 -0
- package/src/runtime/application/index.ts +5 -0
- package/src/runtime/constants.ts +13 -0
- package/src/runtime/core/hooks.ts +5 -0
- package/src/runtime/core/plugin.ts +13 -0
- package/src/runtime/core/runtime.ts +109 -0
- package/src/runtime/enums.ts +24 -0
- package/src/runtime/index.ts +21 -0
- package/src/runtime/injectables.ts +61 -0
- package/src/runtime/jobs/job.ts +370 -0
- package/src/runtime/jobs/manager.ts +332 -0
- package/src/runtime/jobs/router.ts +835 -0
- package/src/runtime/jobs/runner.ts +320 -0
- package/src/runtime/jobs/step.ts +65 -0
- package/src/runtime/jobs/ui.ts +21 -0
- package/src/runtime/pubsub/manager.ts +211 -0
- package/src/runtime/pubsub/redis.ts +108 -0
- package/src/runtime/scheduler/index.ts +39 -0
- package/src/runtime/server/applications.ts +210 -0
- package/src/runtime/server/config.ts +158 -0
- package/src/runtime/server/jobs.ts +250 -0
- package/src/runtime/server/pool.ts +260 -0
- package/src/runtime/server/proxy.ts +118 -0
- package/src/runtime/server/server.ts +155 -0
- package/src/runtime/store/index.ts +30 -0
- package/src/runtime/types.ts +93 -0
- package/src/runtime/workers/application.ts +209 -0
- package/src/runtime/workers/base.ts +68 -0
- package/src/runtime/workers/cli.ts +0 -0
- package/src/runtime/workers/job.ts +153 -0
- package/src/typings.ts +30 -0
- package/src/vite/builder.ts +122 -0
- package/src/vite/config.ts +45 -0
- package/src/vite/plugins.ts +26 -0
- package/src/vite/runners/worker.ts +57 -0
- package/src/vite/server.ts +39 -0
- package/src/vite/servers/main.ts +34 -0
- package/src/vite/servers/worker.ts +143 -0
- package/dist/_exports/application.js +0 -1
- package/dist/_exports/common.js +0 -1
- package/dist/_exports/contract.js +0 -2
- package/dist/_exports/core.js +0 -1
- package/dist/_exports/gateway.js +0 -1
- package/dist/_exports/http-transport/bun.js +0 -1
- package/dist/_exports/http-transport/deno.js +0 -1
- package/dist/_exports/http-transport/node.js +0 -1
- package/dist/_exports/http-transport.js +0 -1
- package/dist/_exports/json-format.js +0 -1
- package/dist/_exports/protocol/client.js +0 -1
- package/dist/_exports/protocol/server.js +0 -1
- package/dist/_exports/protocol.js +0 -1
- package/dist/_exports/runtime/types.js +0 -1
- package/dist/_exports/runtime.js +0 -1
- package/dist/_exports/type.js +0 -2
- package/dist/_exports/ws-transport/bun.js +0 -1
- package/dist/_exports/ws-transport/deno.js +0 -1
- package/dist/_exports/ws-transport/node.js +0 -1
- package/dist/_exports/ws-transport.js +0 -1
- package/dist/command.js +0 -30
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
2
|
+
import { randomUUID } from 'node:crypto'
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
Job,
|
|
6
|
+
JobState,
|
|
7
|
+
JobType,
|
|
8
|
+
QueueEventsListener,
|
|
9
|
+
RedisClient,
|
|
10
|
+
} from 'bullmq'
|
|
11
|
+
import { pick } from '@nmtjs/core'
|
|
12
|
+
import {
|
|
13
|
+
Queue,
|
|
14
|
+
QueueEvents,
|
|
15
|
+
QueueEventsProducer,
|
|
16
|
+
UnrecoverableError,
|
|
17
|
+
} from 'bullmq'
|
|
18
|
+
|
|
19
|
+
import type { ServerStoreConfig } from '../server/config.ts'
|
|
20
|
+
import type { Store } from '../types.ts'
|
|
21
|
+
import type { AnyJob, JobBackoffOptions } from './job.ts'
|
|
22
|
+
import { createStoreClient } from '../store/index.ts'
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get the dedicated BullMQ queue name for a job
|
|
26
|
+
*/
|
|
27
|
+
export function getJobQueueName(job: AnyJob): string {
|
|
28
|
+
return `job.${job.options.name}`
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type QueueJobResultOptions<T extends AnyJob = AnyJob> = {
|
|
32
|
+
job: T
|
|
33
|
+
bullJob: Job<T['_']['input'], T['_']['output'], T['options']['name']>
|
|
34
|
+
events: QueueEvents
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type QueueJobAddOptions = {
|
|
38
|
+
jobId?: string
|
|
39
|
+
priority?: number
|
|
40
|
+
forceMissingWorkers?: boolean
|
|
41
|
+
attempts?: number
|
|
42
|
+
backoff?: JobBackoffOptions
|
|
43
|
+
oneoff?: boolean
|
|
44
|
+
delay?: number
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class QueueJobResult<T extends AnyJob = AnyJob> {
|
|
48
|
+
#options: QueueJobResultOptions<T>
|
|
49
|
+
|
|
50
|
+
constructor(options: QueueJobResultOptions<T>) {
|
|
51
|
+
this.#options = options
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get id() {
|
|
55
|
+
return this.#options.bullJob.id
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get name() {
|
|
59
|
+
return this.#options.job.options.name
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async waitResult() {
|
|
63
|
+
return await this.#options.bullJob.waitUntilFinished(this.#options.events)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type JobItem<T extends AnyJob = AnyJob> = Pick<
|
|
68
|
+
Job<T['_']['input'], T['_']['output'], T['options']['name']>,
|
|
69
|
+
| 'queueName'
|
|
70
|
+
| 'priority'
|
|
71
|
+
| 'progress'
|
|
72
|
+
| 'name'
|
|
73
|
+
| 'data'
|
|
74
|
+
| 'returnvalue'
|
|
75
|
+
| 'attemptsMade'
|
|
76
|
+
| 'processedOn'
|
|
77
|
+
| 'finishedOn'
|
|
78
|
+
| 'failedReason'
|
|
79
|
+
| 'stacktrace'
|
|
80
|
+
> & { id: string; status: JobState | 'unknown' }
|
|
81
|
+
|
|
82
|
+
export interface JobManagerInstance {
|
|
83
|
+
list<T extends AnyJob>(
|
|
84
|
+
job: T,
|
|
85
|
+
options?: { page?: number; limit?: number; state?: JobState[] },
|
|
86
|
+
): Promise<{
|
|
87
|
+
items: JobItem<T>[]
|
|
88
|
+
page: number
|
|
89
|
+
limit: number
|
|
90
|
+
pages: number
|
|
91
|
+
total: number
|
|
92
|
+
}>
|
|
93
|
+
get<T extends AnyJob>(job: T, id: string): Promise<JobItem<T> | null>
|
|
94
|
+
add<T extends AnyJob>(
|
|
95
|
+
job: T,
|
|
96
|
+
data: T['_']['input'],
|
|
97
|
+
options?: QueueJobAddOptions,
|
|
98
|
+
): Promise<QueueJobResult<T>>
|
|
99
|
+
retry(
|
|
100
|
+
job: AnyJob,
|
|
101
|
+
id: string,
|
|
102
|
+
options?: { clearState?: boolean },
|
|
103
|
+
): Promise<void>
|
|
104
|
+
remove(job: AnyJob, id: string): Promise<void>
|
|
105
|
+
cancel(job: AnyJob, id: string): Promise<void>
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export type CustomJobsEvents = QueueEventsListener & {
|
|
109
|
+
[K in `cancel:${string}`]: (args: {}, id: string) => void
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
type JobQueueEntry = {
|
|
113
|
+
queue: Queue
|
|
114
|
+
events: QueueEvents
|
|
115
|
+
custom: QueueEventsProducer
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export class JobManager {
|
|
119
|
+
protected store!: Store
|
|
120
|
+
/**
|
|
121
|
+
* Per-job dedicated queues. Each job has its own queue for granular control.
|
|
122
|
+
*/
|
|
123
|
+
protected jobQueues = new Map<string, JobQueueEntry>()
|
|
124
|
+
|
|
125
|
+
constructor(
|
|
126
|
+
protected storeConfig: ServerStoreConfig,
|
|
127
|
+
protected jobs: AnyJob[],
|
|
128
|
+
) {}
|
|
129
|
+
|
|
130
|
+
get publicInstance(): JobManagerInstance {
|
|
131
|
+
return {
|
|
132
|
+
// @ts-expect-error
|
|
133
|
+
list: this.list.bind(this),
|
|
134
|
+
add: this.add.bind(this),
|
|
135
|
+
get: this.get.bind(this),
|
|
136
|
+
retry: this.retry.bind(this),
|
|
137
|
+
remove: this.remove.bind(this),
|
|
138
|
+
cancel: this.cancel.bind(this),
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async initialize() {
|
|
143
|
+
this.store = await createStoreClient(this.storeConfig)
|
|
144
|
+
await this.store.connect()
|
|
145
|
+
|
|
146
|
+
// Create a dedicated queue for each job
|
|
147
|
+
for (const job of this.jobs) {
|
|
148
|
+
const queueName = getJobQueueName(job)
|
|
149
|
+
const entry: JobQueueEntry = {
|
|
150
|
+
queue: new Queue(queueName, { connection: this.store as RedisClient }),
|
|
151
|
+
events: new QueueEvents(queueName, {
|
|
152
|
+
connection: this.store as RedisClient,
|
|
153
|
+
autorun: true,
|
|
154
|
+
}),
|
|
155
|
+
custom: new QueueEventsProducer(queueName, {
|
|
156
|
+
connection: this.store as RedisClient,
|
|
157
|
+
}),
|
|
158
|
+
}
|
|
159
|
+
this.jobQueues.set(job.options.name, entry)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Wait for all queues to be ready
|
|
163
|
+
await Promise.all(
|
|
164
|
+
Array.from(this.jobQueues.values()).flatMap((entry) => [
|
|
165
|
+
entry.queue.waitUntilReady(),
|
|
166
|
+
entry.events.waitUntilReady(),
|
|
167
|
+
entry.custom.waitUntilReady(),
|
|
168
|
+
]),
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async terminate() {
|
|
173
|
+
await Promise.allSettled(
|
|
174
|
+
Array.from(this.jobQueues.values()).flatMap((entry) => [
|
|
175
|
+
entry.queue.close(),
|
|
176
|
+
entry.events.close(),
|
|
177
|
+
entry.custom.close(),
|
|
178
|
+
]),
|
|
179
|
+
)
|
|
180
|
+
this.store.disconnect(false)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
protected getJobQueue(job: AnyJob): JobQueueEntry {
|
|
184
|
+
const entry = this.jobQueues.get(job.options.name)
|
|
185
|
+
if (!entry) {
|
|
186
|
+
throw new Error(`Job queue for [${job.options.name}] not found`)
|
|
187
|
+
}
|
|
188
|
+
return entry
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async list<T extends AnyJob>(
|
|
192
|
+
job: T,
|
|
193
|
+
{
|
|
194
|
+
limit = 20,
|
|
195
|
+
page = 1,
|
|
196
|
+
state = [],
|
|
197
|
+
}: { page?: number; limit?: number; state?: JobType[] },
|
|
198
|
+
) {
|
|
199
|
+
const { queue } = this.getJobQueue(job)
|
|
200
|
+
const jobsCount = await queue.getJobCountByTypes(...state)
|
|
201
|
+
const totalPages = Math.ceil(jobsCount / limit)
|
|
202
|
+
if (page > totalPages) return []
|
|
203
|
+
const jobs = await queue.getJobs(
|
|
204
|
+
state,
|
|
205
|
+
(page - 1) * limit,
|
|
206
|
+
page * limit - 1,
|
|
207
|
+
)
|
|
208
|
+
const items = await Promise.all(jobs.map((job) => this._mapJob(job)))
|
|
209
|
+
return { items, page, limit, pages: totalPages, total: jobsCount }
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async get<T extends AnyJob>(job: T, id: string) {
|
|
213
|
+
const { queue } = this.getJobQueue(job)
|
|
214
|
+
const bullJob = await queue.getJob(id)
|
|
215
|
+
if (!bullJob) return null
|
|
216
|
+
return await this._mapJob(bullJob)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async add<T extends AnyJob>(
|
|
220
|
+
job: T,
|
|
221
|
+
data: T['_']['input'],
|
|
222
|
+
{
|
|
223
|
+
forceMissingWorkers = false,
|
|
224
|
+
jobId = randomUUID(),
|
|
225
|
+
priority,
|
|
226
|
+
attempts = job.options.attempts,
|
|
227
|
+
backoff = job.options.backoff,
|
|
228
|
+
oneoff = job.options.oneoff ?? true,
|
|
229
|
+
delay,
|
|
230
|
+
}: QueueJobAddOptions = {},
|
|
231
|
+
) {
|
|
232
|
+
const { queue, events } = this.getJobQueue(job)
|
|
233
|
+
|
|
234
|
+
if (!forceMissingWorkers) {
|
|
235
|
+
if ((await queue.getWorkersCount()) === 0) {
|
|
236
|
+
throw new Error(
|
|
237
|
+
`No workers available for [${getJobQueueName(job)}] queue`,
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const bullJob = await queue.add(job.options.name as any, data as any, {
|
|
242
|
+
attempts,
|
|
243
|
+
backoff,
|
|
244
|
+
jobId,
|
|
245
|
+
priority,
|
|
246
|
+
delay,
|
|
247
|
+
removeOnComplete: oneoff,
|
|
248
|
+
removeOnFail: oneoff,
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
return new QueueJobResult({ job, bullJob, events })
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async retry(job: AnyJob, id: string, options?: { clearState?: boolean }) {
|
|
255
|
+
const { queue } = this.getJobQueue(job)
|
|
256
|
+
const bullJob = await queue.getJob(id)
|
|
257
|
+
if (!bullJob) throw new Error(`Job with id [${id}] not found`)
|
|
258
|
+
|
|
259
|
+
const state = await bullJob.getState()
|
|
260
|
+
// For completed jobs, clear state by default so it reruns from scratch
|
|
261
|
+
// For failed jobs, keep state by default so it resumes from checkpoint
|
|
262
|
+
const shouldClearState = options?.clearState ?? state === 'completed'
|
|
263
|
+
|
|
264
|
+
if (shouldClearState) {
|
|
265
|
+
await bullJob.updateProgress({})
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
await bullJob.retry()
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async remove(job: AnyJob, id: string) {
|
|
272
|
+
const { queue } = this.getJobQueue(job)
|
|
273
|
+
const bullJob = await queue.getJob(id)
|
|
274
|
+
if (!bullJob) throw new Error(`Job with id [${id}] not found`)
|
|
275
|
+
await bullJob.remove()
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
async cancel(job: AnyJob, id: string) {
|
|
279
|
+
const { custom, queue } = this.getJobQueue(job)
|
|
280
|
+
const bullJob = await queue.getJob(id)
|
|
281
|
+
if (!bullJob) throw new Error(`Job with id [${id}] not found`)
|
|
282
|
+
if (bullJob.finishedOn) return
|
|
283
|
+
if ((await bullJob.getState()) === 'waiting') {
|
|
284
|
+
return await bullJob.remove()
|
|
285
|
+
}
|
|
286
|
+
if ((await bullJob.getState()) === 'active') {
|
|
287
|
+
await custom.publishEvent({ eventName: `cancel:${id}` })
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
cancellationSignal(job: AnyJob, id: string) {
|
|
292
|
+
const { events } = this.getJobQueue(job)
|
|
293
|
+
const controller = new AbortController()
|
|
294
|
+
const handler = () => {
|
|
295
|
+
controller.abort(new UnrecoverableError('Job cancelled'))
|
|
296
|
+
}
|
|
297
|
+
events.on<CustomJobsEvents>(`cancel:${id}`, handler)
|
|
298
|
+
const signal = controller.signal
|
|
299
|
+
return Object.assign(signal, {
|
|
300
|
+
[Symbol.dispose]: () => {
|
|
301
|
+
events.off<CustomJobsEvents>(`cancel:${id}`, handler)
|
|
302
|
+
},
|
|
303
|
+
})
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
getQueue(job: AnyJob) {
|
|
307
|
+
return this.getJobQueue(job)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
protected async _mapJob(bullJob: Job): Promise<JobItem> {
|
|
311
|
+
const status = await bullJob.getState()
|
|
312
|
+
const id = bullJob.id
|
|
313
|
+
assert(typeof id === 'string', 'Expected job id to be a string')
|
|
314
|
+
return {
|
|
315
|
+
...pick(bullJob, {
|
|
316
|
+
queueName: true,
|
|
317
|
+
priority: true,
|
|
318
|
+
progress: true,
|
|
319
|
+
name: true,
|
|
320
|
+
data: true,
|
|
321
|
+
returnvalue: true,
|
|
322
|
+
attemptsMade: true,
|
|
323
|
+
processedOn: true,
|
|
324
|
+
finishedOn: true,
|
|
325
|
+
failedReason: true,
|
|
326
|
+
stacktrace: true,
|
|
327
|
+
}),
|
|
328
|
+
id,
|
|
329
|
+
status,
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|