@h3ravel/queue 11.0.13 → 11.1.0-alpha.2
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/index.cjs +341 -1
- package/dist/index.d.ts +257 -3
- package/dist/index.js +335 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,339 @@
|
|
|
1
|
+
let __h3ravel_support = require("@h3ravel/support");
|
|
2
|
+
let __h3ravel_contracts = require("@h3ravel/contracts");
|
|
1
3
|
let __h3ravel_core = require("@h3ravel/core");
|
|
2
4
|
|
|
5
|
+
//#region src/Events/JobFailed.ts
|
|
6
|
+
var JobFailed = class {
|
|
7
|
+
/**
|
|
8
|
+
* Create a new event instance.
|
|
9
|
+
*
|
|
10
|
+
* @param connectionName The connection name.
|
|
11
|
+
* @param job The job instance.
|
|
12
|
+
* @param exception The exception that caused the job to fail.
|
|
13
|
+
*/
|
|
14
|
+
constructor(connectionName, job, exception) {
|
|
15
|
+
this.connectionName = connectionName;
|
|
16
|
+
this.job = job;
|
|
17
|
+
this.exception = exception;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/Exceptions/ManuallyFailedException.ts
|
|
23
|
+
var ManuallyFailedException = class extends __h3ravel_support.RuntimeException {};
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/Exceptions/MaxAttemptsExceededException.ts
|
|
27
|
+
var MaxAttemptsExceededException = class MaxAttemptsExceededException extends __h3ravel_support.RuntimeException {
|
|
28
|
+
/**
|
|
29
|
+
* The job instance.
|
|
30
|
+
*/
|
|
31
|
+
job;
|
|
32
|
+
/**
|
|
33
|
+
* Create a new instance for the job.
|
|
34
|
+
*
|
|
35
|
+
* @param job
|
|
36
|
+
*/
|
|
37
|
+
static forJob(job) {
|
|
38
|
+
return (0, __h3ravel_support.tap)(new MaxAttemptsExceededException(job.resolveName() + " has been attempted too many times."), (e) => {
|
|
39
|
+
e.job = job;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/Exceptions/TimeoutExceededException.ts
|
|
46
|
+
var TimeoutExceededException = class TimeoutExceededException extends MaxAttemptsExceededException {
|
|
47
|
+
/**
|
|
48
|
+
* Create a new instance for the job.
|
|
49
|
+
*
|
|
50
|
+
* @param job
|
|
51
|
+
*/
|
|
52
|
+
static forJob(job) {
|
|
53
|
+
return (0, __h3ravel_support.tap)(new TimeoutExceededException(job.resolveName() + " has timed out."), (e) => {
|
|
54
|
+
e.job = job;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/Jobs/JobName.ts
|
|
61
|
+
var JobName = class {
|
|
62
|
+
/**
|
|
63
|
+
* Parse the given job name into a class / method array.
|
|
64
|
+
*
|
|
65
|
+
* @param job
|
|
66
|
+
*/
|
|
67
|
+
static parse(_job) {
|
|
68
|
+
return [{}, ""];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get the resolved name of the queued job class.
|
|
72
|
+
*
|
|
73
|
+
* @param name
|
|
74
|
+
* @param payload
|
|
75
|
+
*/
|
|
76
|
+
static resolve(name, payload) {
|
|
77
|
+
if (!payload.displayName) return payload.displayName;
|
|
78
|
+
return name;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get the class name for queued job class.
|
|
82
|
+
*
|
|
83
|
+
* @param name
|
|
84
|
+
* @param payload
|
|
85
|
+
*/
|
|
86
|
+
static resolveClassName(name, payload) {
|
|
87
|
+
if (typeof payload.data.commandName === "string") return payload.data.commandName;
|
|
88
|
+
return name;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/Jobs/Job.ts
|
|
94
|
+
var Job = class {
|
|
95
|
+
/**
|
|
96
|
+
* The job handler instance.
|
|
97
|
+
*/
|
|
98
|
+
instance;
|
|
99
|
+
/**
|
|
100
|
+
* The IoC container instance.
|
|
101
|
+
*/
|
|
102
|
+
container;
|
|
103
|
+
/**
|
|
104
|
+
* Indicates if the job has been deleted.
|
|
105
|
+
*/
|
|
106
|
+
deleted = false;
|
|
107
|
+
/**
|
|
108
|
+
* Indicates if the job has been released.
|
|
109
|
+
*/
|
|
110
|
+
released = false;
|
|
111
|
+
/**
|
|
112
|
+
* Indicates if the job has failed.
|
|
113
|
+
*/
|
|
114
|
+
failed = false;
|
|
115
|
+
/**
|
|
116
|
+
* The name of the connection the job belongs to.
|
|
117
|
+
*/
|
|
118
|
+
connectionName;
|
|
119
|
+
/**
|
|
120
|
+
* The name of the queue the job belongs to.
|
|
121
|
+
*/
|
|
122
|
+
queue;
|
|
123
|
+
/**
|
|
124
|
+
* Get the UUID of the job.
|
|
125
|
+
*
|
|
126
|
+
* @return string|null
|
|
127
|
+
*/
|
|
128
|
+
uuid() {
|
|
129
|
+
return this.payload()["uuid"] ?? null;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Fire the job.
|
|
133
|
+
*
|
|
134
|
+
* @return void
|
|
135
|
+
*/
|
|
136
|
+
fire() {
|
|
137
|
+
const payload = this.payload();
|
|
138
|
+
const [instance, method] = JobName.parse(payload["job"]);
|
|
139
|
+
(this.instance = this.resolve(instance))[method](this, payload["data"]);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Delete the job from the queue.
|
|
143
|
+
*/
|
|
144
|
+
delete() {
|
|
145
|
+
this.deleted = true;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Determine if the job has been deleted.
|
|
149
|
+
*/
|
|
150
|
+
isDeleted() {
|
|
151
|
+
return this.deleted;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Release the job back into the queue after (n) seconds.
|
|
155
|
+
*
|
|
156
|
+
* @param delay
|
|
157
|
+
*/
|
|
158
|
+
release(delay = 0) {
|
|
159
|
+
this.released = true;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Determine if the job was released back into the queue.
|
|
163
|
+
*
|
|
164
|
+
* @return bool
|
|
165
|
+
*/
|
|
166
|
+
isReleased() {
|
|
167
|
+
return this.released;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Determine if the job has been deleted or released.
|
|
171
|
+
*/
|
|
172
|
+
isDeletedOrReleased() {
|
|
173
|
+
return this.isDeleted() || this.isReleased();
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Determine if the job has been marked as a failure.
|
|
177
|
+
*/
|
|
178
|
+
hasFailed() {
|
|
179
|
+
return this.failed;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Mark the job as "failed".
|
|
183
|
+
*/
|
|
184
|
+
markAsFailed() {
|
|
185
|
+
this.failed = true;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Delete the job, call the "failed" method, and raise the failed job event.
|
|
189
|
+
*
|
|
190
|
+
* @param e
|
|
191
|
+
*/
|
|
192
|
+
fail(e) {
|
|
193
|
+
this.markAsFailed();
|
|
194
|
+
if (this.isDeleted()) return;
|
|
195
|
+
if (this.shouldRollBackDatabaseTransaction(e)) this.container.make("db").connection(this.container.make("config").get("queue.failed.database")).rollBack(0);
|
|
196
|
+
try {
|
|
197
|
+
this.delete();
|
|
198
|
+
this.failedJob(e);
|
|
199
|
+
} finally {
|
|
200
|
+
this.resolve(__h3ravel_contracts.IDispatcher).dispatch(new JobFailed(this.connectionName, this, e || new ManuallyFailedException()));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Determine if the current database transaction should be rolled back to level zero.
|
|
205
|
+
*
|
|
206
|
+
* @param e
|
|
207
|
+
*/
|
|
208
|
+
shouldRollBackDatabaseTransaction(e) {
|
|
209
|
+
return e instanceof TimeoutExceededException && this.container.make("config").get("queue.failed.database") && ["database", "database-uuids"].includes(this.container.make("config").get("queue.failed.driver")) && this.container.has("db");
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Process an exception that caused the job to fail.
|
|
213
|
+
*
|
|
214
|
+
* @param e
|
|
215
|
+
*/
|
|
216
|
+
failedJob(e, ..._args) {
|
|
217
|
+
const payload = this.payload();
|
|
218
|
+
const [classInstance] = JobName.parse(payload.job);
|
|
219
|
+
this.instance = this.resolve(classInstance);
|
|
220
|
+
if (typeof this.instance.failed === "function") this.instance.failedJob(payload.data, e, payload.uuid ?? "", this);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Resolve the given class.
|
|
224
|
+
*/
|
|
225
|
+
resolve(className) {
|
|
226
|
+
return this.container.make(className);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Get the resolved job handler instance.
|
|
230
|
+
*
|
|
231
|
+
* @return mixed
|
|
232
|
+
*/
|
|
233
|
+
getResolvedJob() {
|
|
234
|
+
return this.instance;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Get the decoded body of the job.
|
|
238
|
+
*/
|
|
239
|
+
payload() {
|
|
240
|
+
return JSON.parse(this.getRawBody());
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Get the number of times to attempt a job.
|
|
244
|
+
*
|
|
245
|
+
* @return int|null
|
|
246
|
+
*/
|
|
247
|
+
maxTries() {
|
|
248
|
+
return this.payload()["maxTries"] ?? null;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Get the number of times to attempt a job after an exception.
|
|
252
|
+
*
|
|
253
|
+
* @return int|null
|
|
254
|
+
*/
|
|
255
|
+
maxExceptions() {
|
|
256
|
+
return this.payload()["maxExceptions"] ?? null;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Determine if the job should fail when it timeouts.
|
|
260
|
+
*
|
|
261
|
+
* @return bool
|
|
262
|
+
*/
|
|
263
|
+
shouldFailOnTimeout() {
|
|
264
|
+
return this.payload()["failOnTimeout"] ?? false;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* The number of seconds to wait before retrying a job that encountered an uncaught exception.
|
|
268
|
+
*
|
|
269
|
+
* @return int|int[]|null
|
|
270
|
+
*/
|
|
271
|
+
backoff() {
|
|
272
|
+
return this.payload()["backoff"] ?? this.payload()["delay"] ?? null;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Get the number of seconds the job can run.
|
|
276
|
+
*
|
|
277
|
+
* @return int|null
|
|
278
|
+
*/
|
|
279
|
+
timeout() {
|
|
280
|
+
return this.payload()["timeout"] ?? null;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Get the timestamp indicating when the job should timeout.
|
|
284
|
+
*
|
|
285
|
+
* @return int|null
|
|
286
|
+
*/
|
|
287
|
+
retryUntil() {
|
|
288
|
+
return this.payload()["retryUntil"] ?? null;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Get the name of the queued job class.
|
|
292
|
+
*
|
|
293
|
+
* @return string
|
|
294
|
+
*/
|
|
295
|
+
getName() {
|
|
296
|
+
return this.payload()["job"];
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Get the resolved display name of the queued job class.
|
|
300
|
+
*
|
|
301
|
+
* Resolves the name of "wrapped" jobs such as class-based handlers.
|
|
302
|
+
*/
|
|
303
|
+
resolveName() {
|
|
304
|
+
return JobName.resolve(this.getName(), this.payload());
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Get the class of the queued job.
|
|
308
|
+
*
|
|
309
|
+
* Resolves the class of "wrapped" jobs such as class-based handlers.
|
|
310
|
+
*
|
|
311
|
+
* @return string
|
|
312
|
+
*/
|
|
313
|
+
resolveQueuedJobClass() {
|
|
314
|
+
return JobName.resolveClassName(this.getName(), this.payload());
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Get the name of the connection the job belongs to.
|
|
318
|
+
*/
|
|
319
|
+
getConnectionName() {
|
|
320
|
+
return this.connectionName;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Get the name of the queue the job belongs to.
|
|
324
|
+
*/
|
|
325
|
+
getQueue() {
|
|
326
|
+
return this.queue;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Get the service container instance.
|
|
330
|
+
*/
|
|
331
|
+
getContainer() {
|
|
332
|
+
return this.container;
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
//#endregion
|
|
3
337
|
//#region src/Providers/QueueServiceProvider.ts
|
|
4
338
|
/**
|
|
5
339
|
* Queues and workers.
|
|
@@ -16,4 +350,10 @@ var QueueServiceProvider = class extends __h3ravel_core.ServiceProvider {
|
|
|
16
350
|
};
|
|
17
351
|
|
|
18
352
|
//#endregion
|
|
19
|
-
exports.
|
|
353
|
+
exports.Job = Job;
|
|
354
|
+
exports.JobFailed = JobFailed;
|
|
355
|
+
exports.JobName = JobName;
|
|
356
|
+
exports.ManuallyFailedException = ManuallyFailedException;
|
|
357
|
+
exports.MaxAttemptsExceededException = MaxAttemptsExceededException;
|
|
358
|
+
exports.QueueServiceProvider = QueueServiceProvider;
|
|
359
|
+
exports.TimeoutExceededException = TimeoutExceededException;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,262 @@
|
|
|
1
1
|
/// <reference path="./app.globals.d.ts" />
|
|
2
|
-
import {
|
|
2
|
+
import { ClassConstructor, JobPayload } from "@h3ravel/contracts";
|
|
3
|
+
import { Container, ServiceProvider } from "@h3ravel/core";
|
|
4
|
+
import { RuntimeException } from "@h3ravel/support";
|
|
3
5
|
|
|
6
|
+
//#region src/Contracts/JobContract.d.ts
|
|
7
|
+
type JobClassConstructor = (new (...args: any) => any);
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/Jobs/Job.d.ts
|
|
10
|
+
declare abstract class Job {
|
|
11
|
+
/**
|
|
12
|
+
* The job handler instance.
|
|
13
|
+
*/
|
|
14
|
+
protected instance: Job;
|
|
15
|
+
/**
|
|
16
|
+
* The IoC container instance.
|
|
17
|
+
*/
|
|
18
|
+
protected container: Container;
|
|
19
|
+
/**
|
|
20
|
+
* Indicates if the job has been deleted.
|
|
21
|
+
*/
|
|
22
|
+
protected deleted: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Indicates if the job has been released.
|
|
25
|
+
*/
|
|
26
|
+
protected released: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Indicates if the job has failed.
|
|
29
|
+
*/
|
|
30
|
+
protected failed: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The name of the connection the job belongs to.
|
|
33
|
+
*/
|
|
34
|
+
protected connectionName: string;
|
|
35
|
+
/**
|
|
36
|
+
* The name of the queue the job belongs to.
|
|
37
|
+
*/
|
|
38
|
+
protected queue?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Get the job identifier.
|
|
41
|
+
*/
|
|
42
|
+
abstract getJobId(): string | number | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Get the raw body of the job.
|
|
45
|
+
*/
|
|
46
|
+
abstract getRawBody(): string;
|
|
47
|
+
/**
|
|
48
|
+
* Get the UUID of the job.
|
|
49
|
+
*
|
|
50
|
+
* @return string|null
|
|
51
|
+
*/
|
|
52
|
+
uuid(): string | null;
|
|
53
|
+
/**
|
|
54
|
+
* Fire the job.
|
|
55
|
+
*
|
|
56
|
+
* @return void
|
|
57
|
+
*/
|
|
58
|
+
fire(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Delete the job from the queue.
|
|
61
|
+
*/
|
|
62
|
+
delete(): void;
|
|
63
|
+
/**
|
|
64
|
+
* Determine if the job has been deleted.
|
|
65
|
+
*/
|
|
66
|
+
isDeleted(): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Release the job back into the queue after (n) seconds.
|
|
69
|
+
*
|
|
70
|
+
* @param delay
|
|
71
|
+
*/
|
|
72
|
+
release(delay?: number): void;
|
|
73
|
+
/**
|
|
74
|
+
* Determine if the job was released back into the queue.
|
|
75
|
+
*
|
|
76
|
+
* @return bool
|
|
77
|
+
*/
|
|
78
|
+
isReleased(): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Determine if the job has been deleted or released.
|
|
81
|
+
*/
|
|
82
|
+
isDeletedOrReleased(): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Determine if the job has been marked as a failure.
|
|
85
|
+
*/
|
|
86
|
+
hasFailed(): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Mark the job as "failed".
|
|
89
|
+
*/
|
|
90
|
+
markAsFailed(): void;
|
|
91
|
+
/**
|
|
92
|
+
* Delete the job, call the "failed" method, and raise the failed job event.
|
|
93
|
+
*
|
|
94
|
+
* @param e
|
|
95
|
+
*/
|
|
96
|
+
fail(e: Error): void;
|
|
97
|
+
/**
|
|
98
|
+
* Determine if the current database transaction should be rolled back to level zero.
|
|
99
|
+
*
|
|
100
|
+
* @param e
|
|
101
|
+
*/
|
|
102
|
+
protected shouldRollBackDatabaseTransaction(e: Error): any;
|
|
103
|
+
/**
|
|
104
|
+
* Process an exception that caused the job to fail.
|
|
105
|
+
*
|
|
106
|
+
* @param e
|
|
107
|
+
*/
|
|
108
|
+
protected failedJob(e: Error, ..._args: any[]): void;
|
|
109
|
+
/**
|
|
110
|
+
* Resolve the given class.
|
|
111
|
+
*/
|
|
112
|
+
protected resolve<C extends ClassConstructor>(className: C): InstanceType<C>;
|
|
113
|
+
/**
|
|
114
|
+
* Get the resolved job handler instance.
|
|
115
|
+
*
|
|
116
|
+
* @return mixed
|
|
117
|
+
*/
|
|
118
|
+
getResolvedJob(): Job;
|
|
119
|
+
/**
|
|
120
|
+
* Get the decoded body of the job.
|
|
121
|
+
*/
|
|
122
|
+
payload(): JobPayload;
|
|
123
|
+
/**
|
|
124
|
+
* Get the number of times to attempt a job.
|
|
125
|
+
*
|
|
126
|
+
* @return int|null
|
|
127
|
+
*/
|
|
128
|
+
maxTries(): number | null;
|
|
129
|
+
/**
|
|
130
|
+
* Get the number of times to attempt a job after an exception.
|
|
131
|
+
*
|
|
132
|
+
* @return int|null
|
|
133
|
+
*/
|
|
134
|
+
maxExceptions(): number | null;
|
|
135
|
+
/**
|
|
136
|
+
* Determine if the job should fail when it timeouts.
|
|
137
|
+
*
|
|
138
|
+
* @return bool
|
|
139
|
+
*/
|
|
140
|
+
shouldFailOnTimeout(): boolean;
|
|
141
|
+
/**
|
|
142
|
+
* The number of seconds to wait before retrying a job that encountered an uncaught exception.
|
|
143
|
+
*
|
|
144
|
+
* @return int|int[]|null
|
|
145
|
+
*/
|
|
146
|
+
backoff(): number | null;
|
|
147
|
+
/**
|
|
148
|
+
* Get the number of seconds the job can run.
|
|
149
|
+
*
|
|
150
|
+
* @return int|null
|
|
151
|
+
*/
|
|
152
|
+
timeout(): number | null;
|
|
153
|
+
/**
|
|
154
|
+
* Get the timestamp indicating when the job should timeout.
|
|
155
|
+
*
|
|
156
|
+
* @return int|null
|
|
157
|
+
*/
|
|
158
|
+
retryUntil(): number | null;
|
|
159
|
+
/**
|
|
160
|
+
* Get the name of the queued job class.
|
|
161
|
+
*
|
|
162
|
+
* @return string
|
|
163
|
+
*/
|
|
164
|
+
getName(): string;
|
|
165
|
+
/**
|
|
166
|
+
* Get the resolved display name of the queued job class.
|
|
167
|
+
*
|
|
168
|
+
* Resolves the name of "wrapped" jobs such as class-based handlers.
|
|
169
|
+
*/
|
|
170
|
+
resolveName(): any;
|
|
171
|
+
/**
|
|
172
|
+
* Get the class of the queued job.
|
|
173
|
+
*
|
|
174
|
+
* Resolves the class of "wrapped" jobs such as class-based handlers.
|
|
175
|
+
*
|
|
176
|
+
* @return string
|
|
177
|
+
*/
|
|
178
|
+
resolveQueuedJobClass(): any;
|
|
179
|
+
/**
|
|
180
|
+
* Get the name of the connection the job belongs to.
|
|
181
|
+
*/
|
|
182
|
+
getConnectionName(): string;
|
|
183
|
+
/**
|
|
184
|
+
* Get the name of the queue the job belongs to.
|
|
185
|
+
*/
|
|
186
|
+
getQueue(): string | undefined;
|
|
187
|
+
/**
|
|
188
|
+
* Get the service container instance.
|
|
189
|
+
*/
|
|
190
|
+
getContainer(): Container;
|
|
191
|
+
}
|
|
192
|
+
//#endregion
|
|
193
|
+
//#region src/Events/JobFailed.d.ts
|
|
194
|
+
declare class JobFailed {
|
|
195
|
+
connectionName: string;
|
|
196
|
+
job: Job;
|
|
197
|
+
exception: Error;
|
|
198
|
+
/**
|
|
199
|
+
* Create a new event instance.
|
|
200
|
+
*
|
|
201
|
+
* @param connectionName The connection name.
|
|
202
|
+
* @param job The job instance.
|
|
203
|
+
* @param exception The exception that caused the job to fail.
|
|
204
|
+
*/
|
|
205
|
+
constructor(connectionName: string, job: Job, exception: Error);
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region src/Exceptions/ManuallyFailedException.d.ts
|
|
209
|
+
declare class ManuallyFailedException extends RuntimeException {}
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region src/Exceptions/MaxAttemptsExceededException.d.ts
|
|
212
|
+
declare class MaxAttemptsExceededException extends RuntimeException {
|
|
213
|
+
/**
|
|
214
|
+
* The job instance.
|
|
215
|
+
*/
|
|
216
|
+
job: Job;
|
|
217
|
+
/**
|
|
218
|
+
* Create a new instance for the job.
|
|
219
|
+
*
|
|
220
|
+
* @param job
|
|
221
|
+
*/
|
|
222
|
+
static forJob(job: Job): MaxAttemptsExceededException;
|
|
223
|
+
}
|
|
224
|
+
//#endregion
|
|
225
|
+
//#region src/Exceptions/TimeoutExceededException.d.ts
|
|
226
|
+
declare class TimeoutExceededException extends MaxAttemptsExceededException {
|
|
227
|
+
/**
|
|
228
|
+
* Create a new instance for the job.
|
|
229
|
+
*
|
|
230
|
+
* @param job
|
|
231
|
+
*/
|
|
232
|
+
static forJob(job: Job): TimeoutExceededException;
|
|
233
|
+
}
|
|
234
|
+
//#endregion
|
|
235
|
+
//#region src/Jobs/JobName.d.ts
|
|
236
|
+
declare class JobName {
|
|
237
|
+
/**
|
|
238
|
+
* Parse the given job name into a class / method array.
|
|
239
|
+
*
|
|
240
|
+
* @param job
|
|
241
|
+
*/
|
|
242
|
+
static parse(_job: string): [JobClassConstructor, string];
|
|
243
|
+
/**
|
|
244
|
+
* Get the resolved name of the queued job class.
|
|
245
|
+
*
|
|
246
|
+
* @param name
|
|
247
|
+
* @param payload
|
|
248
|
+
*/
|
|
249
|
+
static resolve(name: string, payload: Record<string, any>): any;
|
|
250
|
+
/**
|
|
251
|
+
* Get the class name for queued job class.
|
|
252
|
+
*
|
|
253
|
+
* @param name
|
|
254
|
+
* @param payload
|
|
255
|
+
*/
|
|
256
|
+
static resolveClassName(name: string, payload: Record<string, any>): any;
|
|
257
|
+
}
|
|
258
|
+
//#endregion
|
|
4
259
|
//#region src/Providers/QueueServiceProvider.d.ts
|
|
5
|
-
|
|
6
260
|
/**
|
|
7
261
|
* Queues and workers.
|
|
8
262
|
*
|
|
@@ -17,4 +271,4 @@ declare class QueueServiceProvider extends ServiceProvider {
|
|
|
17
271
|
register(): void;
|
|
18
272
|
}
|
|
19
273
|
//#endregion
|
|
20
|
-
export { QueueServiceProvider };
|
|
274
|
+
export { Job, JobClassConstructor, JobFailed, JobName, ManuallyFailedException, MaxAttemptsExceededException, QueueServiceProvider, TimeoutExceededException };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,339 @@
|
|
|
1
|
+
import { RuntimeException, tap } from "@h3ravel/support";
|
|
2
|
+
import { IDispatcher } from "@h3ravel/contracts";
|
|
1
3
|
import { ServiceProvider } from "@h3ravel/core";
|
|
2
4
|
|
|
5
|
+
//#region src/Events/JobFailed.ts
|
|
6
|
+
var JobFailed = class {
|
|
7
|
+
/**
|
|
8
|
+
* Create a new event instance.
|
|
9
|
+
*
|
|
10
|
+
* @param connectionName The connection name.
|
|
11
|
+
* @param job The job instance.
|
|
12
|
+
* @param exception The exception that caused the job to fail.
|
|
13
|
+
*/
|
|
14
|
+
constructor(connectionName, job, exception) {
|
|
15
|
+
this.connectionName = connectionName;
|
|
16
|
+
this.job = job;
|
|
17
|
+
this.exception = exception;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/Exceptions/ManuallyFailedException.ts
|
|
23
|
+
var ManuallyFailedException = class extends RuntimeException {};
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/Exceptions/MaxAttemptsExceededException.ts
|
|
27
|
+
var MaxAttemptsExceededException = class MaxAttemptsExceededException extends RuntimeException {
|
|
28
|
+
/**
|
|
29
|
+
* The job instance.
|
|
30
|
+
*/
|
|
31
|
+
job;
|
|
32
|
+
/**
|
|
33
|
+
* Create a new instance for the job.
|
|
34
|
+
*
|
|
35
|
+
* @param job
|
|
36
|
+
*/
|
|
37
|
+
static forJob(job) {
|
|
38
|
+
return tap(new MaxAttemptsExceededException(job.resolveName() + " has been attempted too many times."), (e) => {
|
|
39
|
+
e.job = job;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/Exceptions/TimeoutExceededException.ts
|
|
46
|
+
var TimeoutExceededException = class TimeoutExceededException extends MaxAttemptsExceededException {
|
|
47
|
+
/**
|
|
48
|
+
* Create a new instance for the job.
|
|
49
|
+
*
|
|
50
|
+
* @param job
|
|
51
|
+
*/
|
|
52
|
+
static forJob(job) {
|
|
53
|
+
return tap(new TimeoutExceededException(job.resolveName() + " has timed out."), (e) => {
|
|
54
|
+
e.job = job;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/Jobs/JobName.ts
|
|
61
|
+
var JobName = class {
|
|
62
|
+
/**
|
|
63
|
+
* Parse the given job name into a class / method array.
|
|
64
|
+
*
|
|
65
|
+
* @param job
|
|
66
|
+
*/
|
|
67
|
+
static parse(_job) {
|
|
68
|
+
return [{}, ""];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get the resolved name of the queued job class.
|
|
72
|
+
*
|
|
73
|
+
* @param name
|
|
74
|
+
* @param payload
|
|
75
|
+
*/
|
|
76
|
+
static resolve(name, payload) {
|
|
77
|
+
if (!payload.displayName) return payload.displayName;
|
|
78
|
+
return name;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get the class name for queued job class.
|
|
82
|
+
*
|
|
83
|
+
* @param name
|
|
84
|
+
* @param payload
|
|
85
|
+
*/
|
|
86
|
+
static resolveClassName(name, payload) {
|
|
87
|
+
if (typeof payload.data.commandName === "string") return payload.data.commandName;
|
|
88
|
+
return name;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/Jobs/Job.ts
|
|
94
|
+
var Job = class {
|
|
95
|
+
/**
|
|
96
|
+
* The job handler instance.
|
|
97
|
+
*/
|
|
98
|
+
instance;
|
|
99
|
+
/**
|
|
100
|
+
* The IoC container instance.
|
|
101
|
+
*/
|
|
102
|
+
container;
|
|
103
|
+
/**
|
|
104
|
+
* Indicates if the job has been deleted.
|
|
105
|
+
*/
|
|
106
|
+
deleted = false;
|
|
107
|
+
/**
|
|
108
|
+
* Indicates if the job has been released.
|
|
109
|
+
*/
|
|
110
|
+
released = false;
|
|
111
|
+
/**
|
|
112
|
+
* Indicates if the job has failed.
|
|
113
|
+
*/
|
|
114
|
+
failed = false;
|
|
115
|
+
/**
|
|
116
|
+
* The name of the connection the job belongs to.
|
|
117
|
+
*/
|
|
118
|
+
connectionName;
|
|
119
|
+
/**
|
|
120
|
+
* The name of the queue the job belongs to.
|
|
121
|
+
*/
|
|
122
|
+
queue;
|
|
123
|
+
/**
|
|
124
|
+
* Get the UUID of the job.
|
|
125
|
+
*
|
|
126
|
+
* @return string|null
|
|
127
|
+
*/
|
|
128
|
+
uuid() {
|
|
129
|
+
return this.payload()["uuid"] ?? null;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Fire the job.
|
|
133
|
+
*
|
|
134
|
+
* @return void
|
|
135
|
+
*/
|
|
136
|
+
fire() {
|
|
137
|
+
const payload = this.payload();
|
|
138
|
+
const [instance, method] = JobName.parse(payload["job"]);
|
|
139
|
+
(this.instance = this.resolve(instance))[method](this, payload["data"]);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Delete the job from the queue.
|
|
143
|
+
*/
|
|
144
|
+
delete() {
|
|
145
|
+
this.deleted = true;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Determine if the job has been deleted.
|
|
149
|
+
*/
|
|
150
|
+
isDeleted() {
|
|
151
|
+
return this.deleted;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Release the job back into the queue after (n) seconds.
|
|
155
|
+
*
|
|
156
|
+
* @param delay
|
|
157
|
+
*/
|
|
158
|
+
release(delay = 0) {
|
|
159
|
+
this.released = true;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Determine if the job was released back into the queue.
|
|
163
|
+
*
|
|
164
|
+
* @return bool
|
|
165
|
+
*/
|
|
166
|
+
isReleased() {
|
|
167
|
+
return this.released;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Determine if the job has been deleted or released.
|
|
171
|
+
*/
|
|
172
|
+
isDeletedOrReleased() {
|
|
173
|
+
return this.isDeleted() || this.isReleased();
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Determine if the job has been marked as a failure.
|
|
177
|
+
*/
|
|
178
|
+
hasFailed() {
|
|
179
|
+
return this.failed;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Mark the job as "failed".
|
|
183
|
+
*/
|
|
184
|
+
markAsFailed() {
|
|
185
|
+
this.failed = true;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Delete the job, call the "failed" method, and raise the failed job event.
|
|
189
|
+
*
|
|
190
|
+
* @param e
|
|
191
|
+
*/
|
|
192
|
+
fail(e) {
|
|
193
|
+
this.markAsFailed();
|
|
194
|
+
if (this.isDeleted()) return;
|
|
195
|
+
if (this.shouldRollBackDatabaseTransaction(e)) this.container.make("db").connection(this.container.make("config").get("queue.failed.database")).rollBack(0);
|
|
196
|
+
try {
|
|
197
|
+
this.delete();
|
|
198
|
+
this.failedJob(e);
|
|
199
|
+
} finally {
|
|
200
|
+
this.resolve(IDispatcher).dispatch(new JobFailed(this.connectionName, this, e || new ManuallyFailedException()));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Determine if the current database transaction should be rolled back to level zero.
|
|
205
|
+
*
|
|
206
|
+
* @param e
|
|
207
|
+
*/
|
|
208
|
+
shouldRollBackDatabaseTransaction(e) {
|
|
209
|
+
return e instanceof TimeoutExceededException && this.container.make("config").get("queue.failed.database") && ["database", "database-uuids"].includes(this.container.make("config").get("queue.failed.driver")) && this.container.has("db");
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Process an exception that caused the job to fail.
|
|
213
|
+
*
|
|
214
|
+
* @param e
|
|
215
|
+
*/
|
|
216
|
+
failedJob(e, ..._args) {
|
|
217
|
+
const payload = this.payload();
|
|
218
|
+
const [classInstance] = JobName.parse(payload.job);
|
|
219
|
+
this.instance = this.resolve(classInstance);
|
|
220
|
+
if (typeof this.instance.failed === "function") this.instance.failedJob(payload.data, e, payload.uuid ?? "", this);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Resolve the given class.
|
|
224
|
+
*/
|
|
225
|
+
resolve(className) {
|
|
226
|
+
return this.container.make(className);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Get the resolved job handler instance.
|
|
230
|
+
*
|
|
231
|
+
* @return mixed
|
|
232
|
+
*/
|
|
233
|
+
getResolvedJob() {
|
|
234
|
+
return this.instance;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Get the decoded body of the job.
|
|
238
|
+
*/
|
|
239
|
+
payload() {
|
|
240
|
+
return JSON.parse(this.getRawBody());
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Get the number of times to attempt a job.
|
|
244
|
+
*
|
|
245
|
+
* @return int|null
|
|
246
|
+
*/
|
|
247
|
+
maxTries() {
|
|
248
|
+
return this.payload()["maxTries"] ?? null;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Get the number of times to attempt a job after an exception.
|
|
252
|
+
*
|
|
253
|
+
* @return int|null
|
|
254
|
+
*/
|
|
255
|
+
maxExceptions() {
|
|
256
|
+
return this.payload()["maxExceptions"] ?? null;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Determine if the job should fail when it timeouts.
|
|
260
|
+
*
|
|
261
|
+
* @return bool
|
|
262
|
+
*/
|
|
263
|
+
shouldFailOnTimeout() {
|
|
264
|
+
return this.payload()["failOnTimeout"] ?? false;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* The number of seconds to wait before retrying a job that encountered an uncaught exception.
|
|
268
|
+
*
|
|
269
|
+
* @return int|int[]|null
|
|
270
|
+
*/
|
|
271
|
+
backoff() {
|
|
272
|
+
return this.payload()["backoff"] ?? this.payload()["delay"] ?? null;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Get the number of seconds the job can run.
|
|
276
|
+
*
|
|
277
|
+
* @return int|null
|
|
278
|
+
*/
|
|
279
|
+
timeout() {
|
|
280
|
+
return this.payload()["timeout"] ?? null;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Get the timestamp indicating when the job should timeout.
|
|
284
|
+
*
|
|
285
|
+
* @return int|null
|
|
286
|
+
*/
|
|
287
|
+
retryUntil() {
|
|
288
|
+
return this.payload()["retryUntil"] ?? null;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Get the name of the queued job class.
|
|
292
|
+
*
|
|
293
|
+
* @return string
|
|
294
|
+
*/
|
|
295
|
+
getName() {
|
|
296
|
+
return this.payload()["job"];
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Get the resolved display name of the queued job class.
|
|
300
|
+
*
|
|
301
|
+
* Resolves the name of "wrapped" jobs such as class-based handlers.
|
|
302
|
+
*/
|
|
303
|
+
resolveName() {
|
|
304
|
+
return JobName.resolve(this.getName(), this.payload());
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Get the class of the queued job.
|
|
308
|
+
*
|
|
309
|
+
* Resolves the class of "wrapped" jobs such as class-based handlers.
|
|
310
|
+
*
|
|
311
|
+
* @return string
|
|
312
|
+
*/
|
|
313
|
+
resolveQueuedJobClass() {
|
|
314
|
+
return JobName.resolveClassName(this.getName(), this.payload());
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Get the name of the connection the job belongs to.
|
|
318
|
+
*/
|
|
319
|
+
getConnectionName() {
|
|
320
|
+
return this.connectionName;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Get the name of the queue the job belongs to.
|
|
324
|
+
*/
|
|
325
|
+
getQueue() {
|
|
326
|
+
return this.queue;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Get the service container instance.
|
|
330
|
+
*/
|
|
331
|
+
getContainer() {
|
|
332
|
+
return this.container;
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
//#endregion
|
|
3
337
|
//#region src/Providers/QueueServiceProvider.ts
|
|
4
338
|
/**
|
|
5
339
|
* Queues and workers.
|
|
@@ -16,4 +350,4 @@ var QueueServiceProvider = class extends ServiceProvider {
|
|
|
16
350
|
};
|
|
17
351
|
|
|
18
352
|
//#endregion
|
|
19
|
-
export { QueueServiceProvider };
|
|
353
|
+
export { Job, JobFailed, JobName, ManuallyFailedException, MaxAttemptsExceededException, QueueServiceProvider, TimeoutExceededException };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@h3ravel/queue",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.1.0-alpha.2",
|
|
4
4
|
"description": "Job queues, workers and broadcasting support system for H3ravel.",
|
|
5
5
|
"h3ravel": {
|
|
6
6
|
"providers": [
|
|
@@ -41,13 +41,13 @@
|
|
|
41
41
|
"laravel"
|
|
42
42
|
],
|
|
43
43
|
"peerDependencies": {
|
|
44
|
-
"@h3ravel/core": "^1.
|
|
44
|
+
"@h3ravel/core": "^0.1.0-alpha.2",
|
|
45
|
+
"@h3ravel/contracts": "^0.1.0-alpha.2"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
48
|
"typescript": "^5.4.0"
|
|
48
49
|
},
|
|
49
50
|
"scripts": {
|
|
50
|
-
"barrel": "barrelsby --directory src --delete --singleQuotes",
|
|
51
51
|
"build": "tsdown --config-loader unconfig",
|
|
52
52
|
"dev": "tsx watch src/index.ts",
|
|
53
53
|
"start": "node dist/index.js",
|