@tsed/bullmq 7.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.barrelsby.json +5 -0
- package/README.md +180 -0
- package/coverage/clover.xml +180 -0
- package/coverage/coverage-final.json +5 -0
- package/coverage/coverage-summary.json +6 -0
- package/coverage/lcov-report/Job.ts.html +136 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/decorators/Job.ts.html +136 -0
- package/coverage/lcov-report/decorators/index.html +116 -0
- package/coverage/lcov-report/dispatchers/JobDispatcher.ts.html +148 -0
- package/coverage/lcov-report/dispatchers/index.html +116 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +161 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov-report/src/BullMQModule.ts.html +361 -0
- package/coverage/lcov-report/src/config/config.ts.html +142 -0
- package/coverage/lcov-report/src/config/index.html +116 -0
- package/coverage/lcov-report/src/decorators/Job.ts.html +136 -0
- package/coverage/lcov-report/src/decorators/index.html +116 -0
- package/coverage/lcov-report/src/dispatchers/JobDispatcher.ts.html +151 -0
- package/coverage/lcov-report/src/dispatchers/index.html +116 -0
- package/coverage/lcov-report/src/index.html +116 -0
- package/coverage/lcov-report/src/processors/ProcessorFactory.ts.html +166 -0
- package/coverage/lcov-report/src/processors/index.html +116 -0
- package/coverage/lcov.info +245 -0
- package/jest.config.js +11 -0
- package/lib/cjs/BullMQModule.js +98 -0
- package/lib/cjs/BullMQModule.js.map +1 -0
- package/lib/cjs/config/config.js +3 -0
- package/lib/cjs/config/config.js.map +1 -0
- package/lib/cjs/contracts/JobMethods.js +3 -0
- package/lib/cjs/contracts/JobMethods.js.map +1 -0
- package/lib/cjs/contracts/JobStore.js +3 -0
- package/lib/cjs/contracts/JobStore.js.map +1 -0
- package/lib/cjs/contracts/index.js +9 -0
- package/lib/cjs/contracts/index.js.map +1 -0
- package/lib/cjs/decorators/Job.js +17 -0
- package/lib/cjs/decorators/Job.js.map +1 -0
- package/lib/cjs/decorators/JobController.js +17 -0
- package/lib/cjs/decorators/JobController.js.map +1 -0
- package/lib/cjs/decorators/index.js +8 -0
- package/lib/cjs/decorators/index.js.map +1 -0
- package/lib/cjs/dispatchers/JobDispatcher.js +27 -0
- package/lib/cjs/dispatchers/JobDispatcher.js.map +1 -0
- package/lib/cjs/dispatchers/index.js +8 -0
- package/lib/cjs/dispatchers/index.js.map +1 -0
- package/lib/cjs/index.js +13 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/cjs/package.json +3 -0
- package/lib/cjs/processors/ProcessorFactory.js +20 -0
- package/lib/cjs/processors/ProcessorFactory.js.map +1 -0
- package/lib/esm/BullMQModule.js +95 -0
- package/lib/esm/BullMQModule.js.map +1 -0
- package/lib/esm/config/config.js +2 -0
- package/lib/esm/config/config.js.map +1 -0
- package/lib/esm/contracts/JobMethods.js +2 -0
- package/lib/esm/contracts/JobMethods.js.map +1 -0
- package/lib/esm/contracts/JobStore.js +2 -0
- package/lib/esm/contracts/JobStore.js.map +1 -0
- package/lib/esm/contracts/index.js +6 -0
- package/lib/esm/contracts/index.js.map +1 -0
- package/lib/esm/decorators/JobController.js +13 -0
- package/lib/esm/decorators/JobController.js.map +1 -0
- package/lib/esm/decorators/index.js +5 -0
- package/lib/esm/decorators/index.js.map +1 -0
- package/lib/esm/dispatchers/JobDispatcher.js +24 -0
- package/lib/esm/dispatchers/JobDispatcher.js.map +1 -0
- package/lib/esm/dispatchers/index.js +5 -0
- package/lib/esm/dispatchers/index.js.map +1 -0
- package/lib/esm/index.js +10 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/package.json +3 -0
- package/lib/tsconfig.esm.tsbuildinfo +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/lib/types/BullMQModule.d.ts +14 -0
- package/lib/types/config/config.d.ts +15 -0
- package/lib/types/contracts/JobMethods.d.ts +3 -0
- package/lib/types/contracts/JobStore.d.ts +6 -0
- package/lib/types/contracts/index.d.ts +5 -0
- package/lib/types/decorators/Job.d.ts +2 -0
- package/lib/types/decorators/JobController.d.ts +2 -0
- package/lib/types/decorators/index.d.ts +4 -0
- package/lib/types/dispatchers/JobDispatcher.d.ts +9 -0
- package/lib/types/dispatchers/index.d.ts +4 -0
- package/lib/types/index.d.ts +9 -0
- package/lib/types/processors/ProcessorFactory.d.ts +7 -0
- package/package.json +51 -0
- package/src/BullMQModule.js +149 -0
- package/src/BullMQModule.spec.js +236 -0
- package/src/BullMQModule.spec.ts +184 -0
- package/src/BullMQModule.ts +93 -0
- package/src/config/config.js +2 -0
- package/src/config/config.ts +19 -0
- package/src/contracts/JobMethods.js +2 -0
- package/src/contracts/JobMethods.ts +3 -0
- package/src/contracts/JobStore.js +2 -0
- package/src/contracts/JobStore.ts +7 -0
- package/src/contracts/index.js +21 -0
- package/src/contracts/index.ts +6 -0
- package/src/decorators/Job.js +18 -0
- package/src/decorators/JobController.js +18 -0
- package/src/decorators/JobController.spec.ts +50 -0
- package/src/decorators/JobController.ts +17 -0
- package/src/decorators/index.js +20 -0
- package/src/decorators/index.ts +5 -0
- package/src/dispatchers/JobDispatcher.js +72 -0
- package/src/dispatchers/JobDispatcher.spec.js +98 -0
- package/src/dispatchers/JobDispatcher.spec.ts +52 -0
- package/src/dispatchers/JobDispatcher.ts +22 -0
- package/src/dispatchers/index.js +20 -0
- package/src/dispatchers/index.ts +5 -0
- package/src/index.ts +10 -0
- package/tsconfig.esm.json +39 -0
- package/tsconfig.json +39 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import {BeforeInit, DIContext, runInContext} from "@tsed/common";
|
|
2
|
+
import {Constant, InjectorService, Module} from "@tsed/di";
|
|
3
|
+
import {getComputedType} from "@tsed/schema";
|
|
4
|
+
import {Job, Queue, Worker} from "bullmq";
|
|
5
|
+
import {v4} from "uuid";
|
|
6
|
+
import {BullMQConfig} from "./config/config";
|
|
7
|
+
import {JobMethods} from "./contracts";
|
|
8
|
+
import {JobDispatcher} from "./dispatchers";
|
|
9
|
+
|
|
10
|
+
@Module()
|
|
11
|
+
export class BullMQModule implements BeforeInit {
|
|
12
|
+
@Constant("bullmq")
|
|
13
|
+
private readonly bullmq: BullMQConfig;
|
|
14
|
+
|
|
15
|
+
constructor(private readonly injector: InjectorService, private readonly dispatcher: JobDispatcher) {}
|
|
16
|
+
|
|
17
|
+
$beforeInit() {
|
|
18
|
+
this.buildWorkers();
|
|
19
|
+
this.buildQueues();
|
|
20
|
+
|
|
21
|
+
this.injector.getMany<JobMethods>("bullmq:cron").map((job) => this.dispatcher.dispatch(getComputedType(job)));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private buildQueues() {
|
|
25
|
+
this.bullmq.queues.forEach((queue) => {
|
|
26
|
+
this.injector
|
|
27
|
+
.add(`bullmq.queue.${queue}`, {
|
|
28
|
+
type: "bullmq:queue",
|
|
29
|
+
useValue: new Queue(queue, {
|
|
30
|
+
connection: this.bullmq.connection,
|
|
31
|
+
defaultJobOptions: this.bullmq.defaultJobOptions
|
|
32
|
+
}),
|
|
33
|
+
hooks: {
|
|
34
|
+
$onDestroy: (queue) => queue.close()
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
.invoke<Queue>(`bullmq.queue.${queue}`);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private buildWorkers() {
|
|
42
|
+
(this.bullmq.workerQueues ?? this.bullmq.queues).forEach((queue) => {
|
|
43
|
+
this.injector
|
|
44
|
+
.add(`bullmq.worker.${queue}`, {
|
|
45
|
+
type: "bullmq:worker",
|
|
46
|
+
useValue: new Worker(queue, this.onProcess.bind(this), {
|
|
47
|
+
connection: this.bullmq.connection
|
|
48
|
+
}),
|
|
49
|
+
hooks: {
|
|
50
|
+
$onDestroy: (worker) => worker.close()
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
.invoke<Worker>(`bullmq.worker.${queue}`);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private getJob(name: string, queueName: string) {
|
|
58
|
+
return this.injector.get(`bullmq.job.${queueName}.${name}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private async onProcess(job: Job) {
|
|
62
|
+
const jobService = this.getJob(job.name, job.queueName);
|
|
63
|
+
|
|
64
|
+
if (!jobService) {
|
|
65
|
+
this.injector.logger.warn({
|
|
66
|
+
event: "BULLMQ_JOB_NOT_FOUND",
|
|
67
|
+
message: `Job ${job.name} ${job.queueName} not found`
|
|
68
|
+
});
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const $ctx = new DIContext({
|
|
73
|
+
injector: this.injector,
|
|
74
|
+
logger: this.injector.logger,
|
|
75
|
+
id: job.id || v4().split("-").join("")
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
$ctx.set("BULLMQ_JOB", job);
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
return await runInContext($ctx, () => jobService.handle(job.data, job));
|
|
82
|
+
} catch (er) {
|
|
83
|
+
$ctx.logger.error({
|
|
84
|
+
event: "BULLMQ_JOB_ERROR",
|
|
85
|
+
message: er.message,
|
|
86
|
+
stack: er.stack
|
|
87
|
+
});
|
|
88
|
+
throw er;
|
|
89
|
+
} finally {
|
|
90
|
+
await $ctx.destroy();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {type ConnectionOptions, type DefaultJobOptions} from "bullmq";
|
|
2
|
+
|
|
3
|
+
export type BullMQConfig = {
|
|
4
|
+
queues: string[];
|
|
5
|
+
connection: ConnectionOptions;
|
|
6
|
+
defaultJobOptions?: DefaultJobOptions;
|
|
7
|
+
disableWorker?: boolean;
|
|
8
|
+
// optionally specify for which queues to start a worker for
|
|
9
|
+
// in case not all queues should be worked on
|
|
10
|
+
workerQueues?: string[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
declare global {
|
|
14
|
+
namespace TsED {
|
|
15
|
+
interface Configuration {
|
|
16
|
+
bullmq?: BullMQConfig;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file Automatically generated by barrelsby.
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
17
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
__exportStar(require("./JobMethods"), exports);
|
|
21
|
+
__exportStar(require("./JobStore"), exports);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Job = void 0;
|
|
4
|
+
var core_1 = require("@tsed/core");
|
|
5
|
+
var di_1 = require("@tsed/di");
|
|
6
|
+
function Job(name, queue, opts) {
|
|
7
|
+
if (queue === void 0) { queue = "default"; }
|
|
8
|
+
if (opts === void 0) { opts = {}; }
|
|
9
|
+
return (0, core_1.useDecorators)((0, core_1.StoreMerge)("bullmq", {
|
|
10
|
+
name: name,
|
|
11
|
+
queue: queue,
|
|
12
|
+
opts: opts
|
|
13
|
+
}), (0, di_1.Injectable)({
|
|
14
|
+
provide: "bullmq.job.".concat(queue, ".").concat(name),
|
|
15
|
+
type: opts.repeat ? "bullmq:cron" : "bullmq:job"
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
exports.Job = Job;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JobController = void 0;
|
|
4
|
+
var core_1 = require("@tsed/core");
|
|
5
|
+
var di_1 = require("@tsed/di");
|
|
6
|
+
function JobController(name, queue, opts) {
|
|
7
|
+
if (queue === void 0) { queue = "default"; }
|
|
8
|
+
if (opts === void 0) { opts = {}; }
|
|
9
|
+
return (0, core_1.useDecorators)((0, core_1.StoreMerge)("bullmq", {
|
|
10
|
+
name: name,
|
|
11
|
+
queue: queue,
|
|
12
|
+
opts: opts
|
|
13
|
+
}), (0, di_1.Injectable)({
|
|
14
|
+
provide: "bullmq.job.".concat(queue, ".").concat(name),
|
|
15
|
+
type: opts.repeat ? "bullmq:cron" : "bullmq:job"
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
exports.JobController = JobController;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {JobController} from "./JobController";
|
|
2
|
+
import {Store} from "@tsed/core";
|
|
3
|
+
|
|
4
|
+
describe("JobController", () => {
|
|
5
|
+
it("should set the proper store data", () => {
|
|
6
|
+
@JobController("testjob")
|
|
7
|
+
class TestJob {}
|
|
8
|
+
|
|
9
|
+
const store = Store.from(TestJob).get("bullmq");
|
|
10
|
+
|
|
11
|
+
expect(store.name).toBe("testjob");
|
|
12
|
+
expect(store.queue).toBe("default");
|
|
13
|
+
expect(store.opts).toStrictEqual({});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("should allow settings a custom queue", () => {
|
|
17
|
+
@JobController("testjob", "custom")
|
|
18
|
+
class CustomQueueJob {}
|
|
19
|
+
|
|
20
|
+
const store = Store.from(CustomQueueJob).get("bullmq");
|
|
21
|
+
|
|
22
|
+
expect(store.queue).toBe("custom");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should allow custom options to be set", () => {
|
|
26
|
+
@JobController("testjob", "default", {
|
|
27
|
+
backoff: 69,
|
|
28
|
+
attempts: 42
|
|
29
|
+
})
|
|
30
|
+
class CustomOptionsJob {}
|
|
31
|
+
|
|
32
|
+
const store = Store.from(CustomOptionsJob).get("bullmq");
|
|
33
|
+
|
|
34
|
+
expect(store.opts).toStrictEqual({
|
|
35
|
+
backoff: 69,
|
|
36
|
+
attempts: 42
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should set type for cron jobs", () => {
|
|
41
|
+
@JobController("testjob", "default", {
|
|
42
|
+
repeat: {count: 42}
|
|
43
|
+
})
|
|
44
|
+
class CustomCronJob {}
|
|
45
|
+
|
|
46
|
+
const store = Store.from(CustomCronJob).get("bullmq");
|
|
47
|
+
|
|
48
|
+
expect(store);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {StoreMerge, useDecorators} from "@tsed/core";
|
|
2
|
+
import {Injectable} from "@tsed/di";
|
|
3
|
+
import {JobsOptions} from "bullmq";
|
|
4
|
+
|
|
5
|
+
export function JobController(name: string, queue: string = "default", opts: JobsOptions = {}) {
|
|
6
|
+
return useDecorators(
|
|
7
|
+
StoreMerge("bullmq", {
|
|
8
|
+
name,
|
|
9
|
+
queue,
|
|
10
|
+
opts
|
|
11
|
+
}),
|
|
12
|
+
Injectable({
|
|
13
|
+
provide: `bullmq.job.${queue}.${name}`,
|
|
14
|
+
type: opts.repeat ? "bullmq:cron" : "bullmq:job"
|
|
15
|
+
})
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file Automatically generated by barrelsby.
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
17
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
__exportStar(require("./JobController"), exports);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
9
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
10
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
11
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
12
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
13
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
14
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
18
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
19
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
20
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
21
|
+
function step(op) {
|
|
22
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
23
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
24
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
25
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
26
|
+
switch (op[0]) {
|
|
27
|
+
case 0: case 1: t = op; break;
|
|
28
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
29
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
30
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
31
|
+
default:
|
|
32
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
33
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
34
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
35
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
36
|
+
if (t[2]) _.ops.pop();
|
|
37
|
+
_.trys.pop(); continue;
|
|
38
|
+
}
|
|
39
|
+
op = body.call(thisArg, _);
|
|
40
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
41
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.JobDispatcher = void 0;
|
|
46
|
+
var di_1 = require("@tsed/di");
|
|
47
|
+
var core_1 = require("@tsed/core");
|
|
48
|
+
var JobDispatcher = /** @class */ (function () {
|
|
49
|
+
function JobDispatcher(injector) {
|
|
50
|
+
this.injector = injector;
|
|
51
|
+
}
|
|
52
|
+
// eslint-disable-next-line require-await
|
|
53
|
+
JobDispatcher.prototype.dispatch = function (job, payload) {
|
|
54
|
+
if (payload === void 0) { payload = {}; }
|
|
55
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
56
|
+
var store, queue;
|
|
57
|
+
return __generator(this, function (_a) {
|
|
58
|
+
store = core_1.Store.from(job).get("bullmq");
|
|
59
|
+
queue = this.injector.getMany("bullmq:queue").find(function (queue) { return queue.name === store.queue; });
|
|
60
|
+
if (!queue) {
|
|
61
|
+
throw new Error("Queue(".concat(store.queue, ") not defined"));
|
|
62
|
+
}
|
|
63
|
+
return [2 /*return*/, queue.add(store.name, payload, store.opts)];
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
JobDispatcher = __decorate([
|
|
68
|
+
(0, di_1.Service)()
|
|
69
|
+
], JobDispatcher);
|
|
70
|
+
return JobDispatcher;
|
|
71
|
+
}());
|
|
72
|
+
exports.JobDispatcher = JobDispatcher;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
9
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
10
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
11
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
12
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
13
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
14
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
18
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
19
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
20
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
21
|
+
function step(op) {
|
|
22
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
23
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
24
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
25
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
26
|
+
switch (op[0]) {
|
|
27
|
+
case 0: case 1: t = op; break;
|
|
28
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
29
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
30
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
31
|
+
default:
|
|
32
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
33
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
34
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
35
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
36
|
+
if (t[2]) _.ops.pop();
|
|
37
|
+
_.trys.pop(); continue;
|
|
38
|
+
}
|
|
39
|
+
op = body.call(thisArg, _);
|
|
40
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
41
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
var di_1 = require("@tsed/di");
|
|
46
|
+
var JobDispatcher_1 = require("./JobDispatcher");
|
|
47
|
+
var decorators_1 = require("../decorators");
|
|
48
|
+
var bullmq_1 = require("bullmq");
|
|
49
|
+
var ts_mockito_1 = require("ts-mockito");
|
|
50
|
+
var ExampleTestJob = /** @class */ (function () {
|
|
51
|
+
function ExampleTestJob() {
|
|
52
|
+
}
|
|
53
|
+
ExampleTestJob.prototype.handle = function (payload) { };
|
|
54
|
+
ExampleTestJob = __decorate([
|
|
55
|
+
(0, decorators_1.JobController)("example-job", "default", {
|
|
56
|
+
backoff: 69
|
|
57
|
+
})
|
|
58
|
+
], ExampleTestJob);
|
|
59
|
+
return ExampleTestJob;
|
|
60
|
+
}());
|
|
61
|
+
var NotConfiguredQueueTestJob = /** @class */ (function () {
|
|
62
|
+
function NotConfiguredQueueTestJob() {
|
|
63
|
+
}
|
|
64
|
+
NotConfiguredQueueTestJob.prototype.handle = function () { };
|
|
65
|
+
NotConfiguredQueueTestJob = __decorate([
|
|
66
|
+
(0, decorators_1.JobController)("queue-not-configured", "not-configured")
|
|
67
|
+
], NotConfiguredQueueTestJob);
|
|
68
|
+
return NotConfiguredQueueTestJob;
|
|
69
|
+
}());
|
|
70
|
+
describe("JobDispatcher", function () {
|
|
71
|
+
it("should throw an exception when a queue is not configured", function () {
|
|
72
|
+
var injector = (0, ts_mockito_1.mock)(di_1.InjectorService);
|
|
73
|
+
(0, ts_mockito_1.when)(injector.getMany("bullmq:queue")).thenReturn([]);
|
|
74
|
+
var dispatcher = new JobDispatcher_1.JobDispatcher((0, ts_mockito_1.instance)(injector));
|
|
75
|
+
expect(dispatcher.dispatch(NotConfiguredQueueTestJob)).rejects.toThrow(new Error("Queue(not-configured) not defined"));
|
|
76
|
+
(0, ts_mockito_1.verify)(injector.getMany("bullmq:queue")).once();
|
|
77
|
+
});
|
|
78
|
+
it("should dispatch job", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
79
|
+
var injector, queue, dispatcher;
|
|
80
|
+
return __generator(this, function (_a) {
|
|
81
|
+
switch (_a.label) {
|
|
82
|
+
case 0:
|
|
83
|
+
injector = (0, ts_mockito_1.mock)(di_1.InjectorService);
|
|
84
|
+
queue = (0, ts_mockito_1.mock)(bullmq_1.Queue);
|
|
85
|
+
(0, ts_mockito_1.when)(queue.name).thenReturn("default");
|
|
86
|
+
(0, ts_mockito_1.when)(injector.getMany("bullmq:queue")).thenReturn([(0, ts_mockito_1.instance)(queue)]);
|
|
87
|
+
dispatcher = new JobDispatcher_1.JobDispatcher((0, ts_mockito_1.instance)(injector));
|
|
88
|
+
return [4 /*yield*/, dispatcher.dispatch(ExampleTestJob, { msg: "hello test" })];
|
|
89
|
+
case 1:
|
|
90
|
+
_a.sent();
|
|
91
|
+
(0, ts_mockito_1.verify)(queue.add("example-job", (0, ts_mockito_1.objectContaining)({ msg: "hello test" }), (0, ts_mockito_1.objectContaining)({
|
|
92
|
+
backoff: 69
|
|
93
|
+
}))).once();
|
|
94
|
+
return [2 /*return*/];
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}); });
|
|
98
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import {InjectorService} from "@tsed/di";
|
|
2
|
+
import {JobDispatcher} from "./JobDispatcher";
|
|
3
|
+
import {JobMethods} from "../contracts";
|
|
4
|
+
import {JobController} from "../decorators";
|
|
5
|
+
import {Queue} from "bullmq";
|
|
6
|
+
import {instance, mock, verify, when, objectContaining} from "ts-mockito";
|
|
7
|
+
|
|
8
|
+
@JobController("example-job", "default", {
|
|
9
|
+
backoff: 69
|
|
10
|
+
})
|
|
11
|
+
class ExampleTestJob implements JobMethods {
|
|
12
|
+
handle(payload: {msg: string}) {}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@JobController("queue-not-configured", "not-configured")
|
|
16
|
+
class NotConfiguredQueueTestJob implements JobMethods {
|
|
17
|
+
handle() {}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe("JobDispatcher", () => {
|
|
21
|
+
it("should throw an exception when a queue is not configured", () => {
|
|
22
|
+
const injector = mock(InjectorService);
|
|
23
|
+
when(injector.getMany("bullmq:queue")).thenReturn([]);
|
|
24
|
+
|
|
25
|
+
const dispatcher = new JobDispatcher(instance(injector));
|
|
26
|
+
|
|
27
|
+
expect(dispatcher.dispatch(NotConfiguredQueueTestJob)).rejects.toThrow(new Error("Queue(not-configured) not defined"));
|
|
28
|
+
verify(injector.getMany("bullmq:queue")).once();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("should dispatch job", async () => {
|
|
32
|
+
const injector = mock(InjectorService);
|
|
33
|
+
const queue = mock(Queue);
|
|
34
|
+
when(queue.name).thenReturn("default");
|
|
35
|
+
|
|
36
|
+
when(injector.getMany("bullmq:queue")).thenReturn([instance(queue)]);
|
|
37
|
+
|
|
38
|
+
const dispatcher = new JobDispatcher(instance(injector));
|
|
39
|
+
|
|
40
|
+
await dispatcher.dispatch(ExampleTestJob, {msg: "hello test"});
|
|
41
|
+
|
|
42
|
+
verify(
|
|
43
|
+
queue.add(
|
|
44
|
+
"example-job",
|
|
45
|
+
objectContaining({msg: "hello test"}),
|
|
46
|
+
objectContaining({
|
|
47
|
+
backoff: 69
|
|
48
|
+
})
|
|
49
|
+
)
|
|
50
|
+
).once();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {InjectorService, Service} from "@tsed/di";
|
|
2
|
+
import {JobMethods, type JobStore} from "../contracts";
|
|
3
|
+
import {Store, Type} from "@tsed/core";
|
|
4
|
+
import {Job as BullMQJob, Queue} from "bullmq";
|
|
5
|
+
|
|
6
|
+
@Service()
|
|
7
|
+
export class JobDispatcher {
|
|
8
|
+
constructor(private readonly injector: InjectorService) {}
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line require-await
|
|
11
|
+
public async dispatch<T extends JobMethods>(job: Type<JobMethods>, payload: Parameters<T["handle"]>[0] = {}): Promise<BullMQJob> {
|
|
12
|
+
const store = Store.from(job).get<JobStore>("bullmq");
|
|
13
|
+
|
|
14
|
+
const queue = this.injector.getMany<Queue>("bullmq:queue").find((queue) => queue.name === store.queue);
|
|
15
|
+
|
|
16
|
+
if (!queue) {
|
|
17
|
+
throw new Error(`Queue(${store.queue}) not defined`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return queue.add(store.name, payload, store.opts);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file Automatically generated by barrelsby.
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
17
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
__exportStar(require("./JobDispatcher"), exports);
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Automatically generated by barrelsby.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export * from "./BullMQModule";
|
|
6
|
+
export * from "./config/config";
|
|
7
|
+
export * from "./contracts/JobMethods";
|
|
8
|
+
export * from "./contracts/JobStore";
|
|
9
|
+
export * from "./decorators/JobController";
|
|
10
|
+
export * from "./dispatchers/JobDispatcher";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@tsed/typescript/tsconfig.node.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"baseUrl": ".",
|
|
5
|
+
"module": "ES2020",
|
|
6
|
+
"rootDir": "src",
|
|
7
|
+
"outDir": "./lib/esm",
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"declarationDir": "./lib/types",
|
|
10
|
+
"composite": true,
|
|
11
|
+
"noEmit": false
|
|
12
|
+
},
|
|
13
|
+
"include": ["src", "src/**/*.json"],
|
|
14
|
+
"exclude": [
|
|
15
|
+
"node_modules",
|
|
16
|
+
"test",
|
|
17
|
+
"lib",
|
|
18
|
+
"benchmark",
|
|
19
|
+
"coverage",
|
|
20
|
+
"spec",
|
|
21
|
+
"**/*.benchmark.ts",
|
|
22
|
+
"**/*.spec.ts",
|
|
23
|
+
"keys",
|
|
24
|
+
"jest.config.js",
|
|
25
|
+
"**/__mock__/**",
|
|
26
|
+
"webpack.config.js"
|
|
27
|
+
],
|
|
28
|
+
"references": [
|
|
29
|
+
{
|
|
30
|
+
"path": "../../platform/common"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"path": "../../core"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"path": "../../di"
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|