@monque/tsed 0.1.0 → 1.0.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/README.md +18 -18
- package/dist/CHANGELOG.md +19 -0
- package/dist/README.md +18 -18
- package/dist/index.cjs +101 -88
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -63
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +78 -64
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +98 -85
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
- package/src/config/config.ts +4 -2
- package/src/config/types.ts +35 -2
- package/src/constants/constants.ts +1 -1
- package/src/constants/types.ts +3 -3
- package/src/decorators/cron.ts +5 -5
- package/src/decorators/index.ts +5 -5
- package/src/decorators/{worker-controller.ts → job-controller.ts} +14 -14
- package/src/decorators/{worker.ts → job.ts} +14 -14
- package/src/decorators/types.ts +18 -18
- package/src/index.ts +7 -7
- package/src/monque-module.ts +23 -18
- package/src/utils/build-job-name.ts +2 -2
- package/src/utils/collect-job-metadata.ts +95 -0
- package/src/utils/get-job-token.ts +29 -0
- package/src/utils/index.ts +4 -4
- package/src/utils/resolve-database.ts +6 -5
- package/src/utils/collect-worker-metadata.ts +0 -95
- package/src/utils/get-worker-token.ts +0 -27
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monque/tsed",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Ts.ED integration for Monque - A robust, type-safe MongoDB job queue for TypeScript",
|
|
5
5
|
"author": "Maurice de Bruyn <debruyn.maurice@gmail.com>",
|
|
6
6
|
"repository": {
|
|
@@ -68,11 +68,11 @@
|
|
|
68
68
|
"lint": "biome check ."
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
|
-
"@monque/core": "^1.
|
|
71
|
+
"@monque/core": "^1.2.0",
|
|
72
72
|
"@tsed/core": "^8.24.1",
|
|
73
73
|
"@tsed/di": "^8.24.1",
|
|
74
74
|
"@tsed/mongoose": "^8.24.1",
|
|
75
|
-
"mongodb": "
|
|
75
|
+
"mongodb": "catalog:"
|
|
76
76
|
},
|
|
77
77
|
"peerDependenciesMeta": {
|
|
78
78
|
"@tsed/mongoose": {
|
|
@@ -81,18 +81,18 @@
|
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@monque/core": "workspace:*",
|
|
84
|
-
"@testcontainers/mongodb": "
|
|
85
|
-
"@total-typescript/ts-reset": "
|
|
84
|
+
"@testcontainers/mongodb": "catalog:",
|
|
85
|
+
"@total-typescript/ts-reset": "catalog:",
|
|
86
86
|
"@tsed/core": "^8.24.1",
|
|
87
87
|
"@tsed/di": "^8.24.1",
|
|
88
88
|
"@tsed/mongoose": "^8.24.1",
|
|
89
89
|
"@tsed/platform-http": "^8.24.1",
|
|
90
90
|
"@tsed/testcontainers-mongo": "^8.24.1",
|
|
91
|
-
"@types/
|
|
92
|
-
"@vitest/coverage-v8": "
|
|
93
|
-
"mongodb": "
|
|
91
|
+
"@types/node": "catalog:",
|
|
92
|
+
"@vitest/coverage-v8": "catalog:",
|
|
93
|
+
"mongodb": "catalog:",
|
|
94
94
|
"testcontainers": "^11.11.0",
|
|
95
|
-
"tsdown": "
|
|
96
|
-
"vitest": "
|
|
95
|
+
"tsdown": "catalog:",
|
|
96
|
+
"vitest": "catalog:"
|
|
97
97
|
}
|
|
98
98
|
}
|
package/src/config/config.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Defines the configuration interface and TsED module augmentation.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { MonqueError } from '@monque/core';
|
|
8
|
+
|
|
7
9
|
import type { MonqueTsedConfig } from './types.js';
|
|
8
10
|
|
|
9
11
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -47,13 +49,13 @@ export function validateDatabaseConfig(config: MonqueTsedConfig): void {
|
|
|
47
49
|
const strategies = [config.db, config.dbFactory, config.dbToken].filter(Boolean);
|
|
48
50
|
|
|
49
51
|
if (strategies.length === 0) {
|
|
50
|
-
throw new
|
|
52
|
+
throw new MonqueError(
|
|
51
53
|
"MonqueTsedConfig requires exactly one of 'db', 'dbFactory', or 'dbToken' to be set",
|
|
52
54
|
);
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
if (strategies.length > 1) {
|
|
56
|
-
throw new
|
|
58
|
+
throw new MonqueError(
|
|
57
59
|
"MonqueTsedConfig accepts only one of 'db', 'dbFactory', or 'dbToken' - multiple were provided",
|
|
58
60
|
);
|
|
59
61
|
}
|
package/src/config/types.ts
CHANGED
|
@@ -24,12 +24,12 @@ import type { Db } from 'mongodb';
|
|
|
24
24
|
* export class Server {}
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
|
-
export interface MonqueTsedConfig extends
|
|
27
|
+
export interface MonqueTsedConfig extends MonqueOptions {
|
|
28
28
|
/**
|
|
29
29
|
* Enable or disable the Monque module.
|
|
30
30
|
*
|
|
31
31
|
* When disabled:
|
|
32
|
-
* -
|
|
32
|
+
* - Jobs are not registered
|
|
33
33
|
* - Lifecycle hooks are no-ops
|
|
34
34
|
* - MonqueService throws on access
|
|
35
35
|
*
|
|
@@ -111,4 +111,37 @@ export interface MonqueTsedConfig extends Omit<MonqueOptions, 'db'> {
|
|
|
111
111
|
* @default "default"
|
|
112
112
|
*/
|
|
113
113
|
mongooseConnectionId?: string;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Disable job processing on this instance.
|
|
117
|
+
*
|
|
118
|
+
* When true, the module will initialize the database connection (allowing you to
|
|
119
|
+
* enqueue jobs via MonqueService) but will NOT register jobs or start the
|
|
120
|
+
* polling loop. Useful for "Producer-only" nodes like API servers that only
|
|
121
|
+
* enqueue jobs but don't process them.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```typescript
|
|
125
|
+
* // API Server (Producer-only)
|
|
126
|
+
* @Configuration({
|
|
127
|
+
* monque: {
|
|
128
|
+
* dbFactory: async () => client.db('myapp'),
|
|
129
|
+
* disableJobProcessing: true, // Only enqueue, don't process
|
|
130
|
+
* }
|
|
131
|
+
* })
|
|
132
|
+
* export class ApiServer {}
|
|
133
|
+
*
|
|
134
|
+
* // Job Server (Consumer)
|
|
135
|
+
* @Configuration({
|
|
136
|
+
* monque: {
|
|
137
|
+
* dbFactory: async () => client.db('myapp'),
|
|
138
|
+
* // disableJobProcessing defaults to false - processes jobs
|
|
139
|
+
* }
|
|
140
|
+
* })
|
|
141
|
+
* export class JobServer {}
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* @default false
|
|
145
|
+
*/
|
|
146
|
+
disableJobProcessing?: boolean;
|
|
114
147
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Symbol used to store decorator metadata on class constructors.
|
|
3
3
|
*
|
|
4
|
-
* Used by @
|
|
4
|
+
* Used by @JobController, @Job, and @Cron decorators to attach
|
|
5
5
|
* metadata that is later collected by MonqueModule during initialization.
|
|
6
6
|
*
|
|
7
7
|
* @example
|
package/src/constants/types.ts
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* These constants are used to categorize providers registered with Ts.ED's
|
|
5
5
|
* dependency injection container, enabling MonqueModule to discover and
|
|
6
|
-
* register
|
|
6
|
+
* register jobs automatically.
|
|
7
7
|
*
|
|
8
8
|
* Note: Using string constants with `as const` instead of enums per
|
|
9
9
|
* Constitution guidelines.
|
|
10
10
|
*/
|
|
11
11
|
export const ProviderTypes = {
|
|
12
|
-
/** Provider type for @
|
|
13
|
-
|
|
12
|
+
/** Provider type for @JobController decorated classes */
|
|
13
|
+
JOB_CONTROLLER: 'monque:job-controller',
|
|
14
14
|
/** Provider type for cron job handlers */
|
|
15
15
|
CRON: 'monque:cron',
|
|
16
16
|
} as const;
|
package/src/decorators/cron.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Store } from '@tsed/core';
|
|
2
2
|
|
|
3
3
|
import { MONQUE } from '@/constants';
|
|
4
|
-
import type { CronDecoratorOptions, CronMetadata,
|
|
4
|
+
import type { CronDecoratorOptions, CronMetadata, JobStore } from '@/decorators/types.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Method decorator that registers a method as a scheduled cron job.
|
|
@@ -11,8 +11,8 @@ import type { CronDecoratorOptions, CronMetadata, WorkerStore } from '@/decorato
|
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
13
|
* ```typescript
|
|
14
|
-
* @
|
|
15
|
-
* class
|
|
14
|
+
* @JobController()
|
|
15
|
+
* class ReportJobs {
|
|
16
16
|
* @Cron("@daily", { timezone: "UTC" })
|
|
17
17
|
* async generateDailyReport() {
|
|
18
18
|
* // ...
|
|
@@ -41,9 +41,9 @@ export function Cron(pattern: string, options?: CronDecoratorOptions): MethodDec
|
|
|
41
41
|
const store = Store.from(targetConstructor);
|
|
42
42
|
|
|
43
43
|
// Get or initialize the MONQUE store
|
|
44
|
-
const existing = store.get<Partial<
|
|
44
|
+
const existing = store.get<Partial<JobStore>>(MONQUE) || {
|
|
45
45
|
type: 'controller',
|
|
46
|
-
|
|
46
|
+
jobs: [],
|
|
47
47
|
cronJobs: [],
|
|
48
48
|
};
|
|
49
49
|
|
package/src/decorators/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export { Cron } from './cron.js';
|
|
2
|
+
export { Job } from './job.js';
|
|
3
|
+
export { JobController } from './job-controller.js';
|
|
2
4
|
export type {
|
|
3
5
|
CronDecoratorOptions,
|
|
4
6
|
CronMetadata,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
JobDecoratorOptions,
|
|
8
|
+
JobMetadata,
|
|
9
|
+
JobStore,
|
|
8
10
|
} from './types.js';
|
|
9
|
-
export { Worker } from './worker.js';
|
|
10
|
-
export { WorkerController } from './worker-controller.js';
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @
|
|
2
|
+
* @JobController class decorator
|
|
3
3
|
*
|
|
4
|
-
* Marks a class as containing
|
|
5
|
-
*
|
|
4
|
+
* Marks a class as containing job methods and registers it with the Ts.ED DI container.
|
|
5
|
+
* Jobs in the class will have their job names prefixed with the namespace.
|
|
6
6
|
*
|
|
7
7
|
* @param namespace - Optional prefix for all job names in this controller.
|
|
8
8
|
* When set, job names become "{namespace}.{name}".
|
|
9
9
|
*
|
|
10
10
|
* @example
|
|
11
11
|
* ```typescript
|
|
12
|
-
* @
|
|
13
|
-
* export class
|
|
14
|
-
* @
|
|
12
|
+
* @JobController("email")
|
|
13
|
+
* export class EmailJobs {
|
|
14
|
+
* @Job("send") // Registered as "email.send"
|
|
15
15
|
* async send(job: Job<EmailPayload>) { }
|
|
16
16
|
* }
|
|
17
17
|
* ```
|
|
@@ -21,35 +21,35 @@ import { Injectable } from '@tsed/di';
|
|
|
21
21
|
|
|
22
22
|
import { MONQUE, ProviderTypes } from '@/constants';
|
|
23
23
|
|
|
24
|
-
import type {
|
|
24
|
+
import type { JobStore } from './types.js';
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
* Class decorator that registers a class as a
|
|
27
|
+
* Class decorator that registers a class as a job controller.
|
|
28
28
|
*
|
|
29
29
|
* @param namespace - Optional namespace prefix for job names
|
|
30
30
|
*/
|
|
31
|
-
export function
|
|
31
|
+
export function JobController(namespace?: string): ClassDecorator {
|
|
32
32
|
return useDecorators(
|
|
33
33
|
// Register as injectable with custom provider type
|
|
34
34
|
Injectable({
|
|
35
|
-
type: ProviderTypes.
|
|
35
|
+
type: ProviderTypes.JOB_CONTROLLER,
|
|
36
36
|
}),
|
|
37
37
|
// Apply custom decorator to store metadata
|
|
38
38
|
(target: object) => {
|
|
39
39
|
const store = Store.from(target);
|
|
40
40
|
|
|
41
41
|
// Get existing store or create new one
|
|
42
|
-
const existing = store.get<Partial<
|
|
42
|
+
const existing = store.get<Partial<JobStore>>(MONQUE) || {};
|
|
43
43
|
|
|
44
44
|
// Merge with new metadata, only include namespace if defined
|
|
45
|
-
const
|
|
45
|
+
const jobStore: JobStore = {
|
|
46
46
|
type: 'controller',
|
|
47
47
|
...(namespace !== undefined && { namespace }),
|
|
48
|
-
|
|
48
|
+
jobs: existing.jobs || [],
|
|
49
49
|
cronJobs: existing.cronJobs || [],
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
store.set(MONQUE,
|
|
52
|
+
store.set(MONQUE, jobStore);
|
|
53
53
|
},
|
|
54
54
|
);
|
|
55
55
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @
|
|
2
|
+
* @Job method decorator
|
|
3
3
|
*
|
|
4
4
|
* Registers a method as a job handler. The method will be called when a job
|
|
5
5
|
* with the matching name is picked up for processing.
|
|
6
6
|
*
|
|
7
7
|
* @param name - Job name (combined with controller namespace if present).
|
|
8
|
-
* @param options -
|
|
8
|
+
* @param options - Job configuration options.
|
|
9
9
|
*
|
|
10
10
|
* @example
|
|
11
11
|
* ```typescript
|
|
12
|
-
* @
|
|
13
|
-
* export class
|
|
14
|
-
* @
|
|
12
|
+
* @JobController("notifications")
|
|
13
|
+
* export class NotificationJobs {
|
|
14
|
+
* @Job("push", { concurrency: 10 })
|
|
15
15
|
* async sendPush(job: Job<PushPayload>) {
|
|
16
16
|
* await pushService.send(job.data);
|
|
17
17
|
* }
|
|
@@ -22,15 +22,15 @@ import { Store } from '@tsed/core';
|
|
|
22
22
|
|
|
23
23
|
import { MONQUE } from '@/constants';
|
|
24
24
|
|
|
25
|
-
import type {
|
|
25
|
+
import type { JobDecoratorOptions, JobMetadata, JobStore } from './types.js';
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Method decorator that registers a method as a job handler.
|
|
29
29
|
*
|
|
30
30
|
* @param name - The job name (will be prefixed with controller namespace if present)
|
|
31
|
-
* @param options - Optional
|
|
31
|
+
* @param options - Optional job configuration (concurrency, replace, etc.)
|
|
32
32
|
*/
|
|
33
|
-
export function
|
|
33
|
+
export function Job(name: string, options?: JobDecoratorOptions): MethodDecorator {
|
|
34
34
|
return <T>(
|
|
35
35
|
target: object,
|
|
36
36
|
propertyKey: string | symbol,
|
|
@@ -38,7 +38,7 @@ export function Worker(name: string, options?: WorkerDecoratorOptions): MethodDe
|
|
|
38
38
|
): void => {
|
|
39
39
|
const methodName = String(propertyKey);
|
|
40
40
|
|
|
41
|
-
const
|
|
41
|
+
const jobMetadata: JobMetadata = {
|
|
42
42
|
name,
|
|
43
43
|
method: methodName,
|
|
44
44
|
opts: options || {},
|
|
@@ -49,18 +49,18 @@ export function Worker(name: string, options?: WorkerDecoratorOptions): MethodDe
|
|
|
49
49
|
const store = Store.from(targetConstructor);
|
|
50
50
|
|
|
51
51
|
// Get or initialize the MONQUE store
|
|
52
|
-
const existing = store.get<Partial<
|
|
52
|
+
const existing = store.get<Partial<JobStore>>(MONQUE) || {
|
|
53
53
|
type: 'controller',
|
|
54
|
-
|
|
54
|
+
jobs: [],
|
|
55
55
|
cronJobs: [],
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
// Add this
|
|
59
|
-
const
|
|
58
|
+
// Add this job to the list
|
|
59
|
+
const jobs = [...(existing.jobs || []), jobMetadata];
|
|
60
60
|
|
|
61
61
|
store.set(MONQUE, {
|
|
62
62
|
...existing,
|
|
63
|
-
|
|
63
|
+
jobs,
|
|
64
64
|
});
|
|
65
65
|
};
|
|
66
66
|
}
|
package/src/decorators/types.ts
CHANGED
|
@@ -5,27 +5,27 @@
|
|
|
5
5
|
import type { WorkerOptions as CoreWorkerOptions, ScheduleOptions } from '@monque/core';
|
|
6
6
|
|
|
7
7
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
8
|
-
//
|
|
8
|
+
// Job Decorator Options
|
|
9
9
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Options for the @
|
|
12
|
+
* Options for the @Job method decorator.
|
|
13
13
|
*
|
|
14
14
|
* Maps to @monque/core WorkerOptions. All standard Monque worker options
|
|
15
15
|
* are exposed here for decorator-based configuration.
|
|
16
16
|
*/
|
|
17
|
-
export interface
|
|
17
|
+
export interface JobDecoratorOptions extends CoreWorkerOptions {}
|
|
18
18
|
|
|
19
19
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
|
-
//
|
|
20
|
+
// Job Metadata
|
|
21
21
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* Metadata for a single @
|
|
24
|
+
* Metadata for a single @Job decorated method.
|
|
25
25
|
*
|
|
26
|
-
* Stored in the
|
|
26
|
+
* Stored in the JobStore and used by MonqueModule to register workers.
|
|
27
27
|
*/
|
|
28
|
-
export interface
|
|
28
|
+
export interface JobMetadata {
|
|
29
29
|
/**
|
|
30
30
|
* Job name (without namespace prefix).
|
|
31
31
|
* Combined with controller namespace to form full job name.
|
|
@@ -38,9 +38,9 @@ export interface WorkerMetadata {
|
|
|
38
38
|
method: string;
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
41
|
+
* Job options forwarded to Monque.register().
|
|
42
42
|
*/
|
|
43
|
-
opts:
|
|
43
|
+
opts: JobDecoratorOptions;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -66,7 +66,7 @@ export interface CronDecoratorOptions extends ScheduleOptions {
|
|
|
66
66
|
/**
|
|
67
67
|
* Metadata for a single @Cron decorated method.
|
|
68
68
|
*
|
|
69
|
-
* Stored in the
|
|
69
|
+
* Stored in the JobStore and used by MonqueModule to schedule cron jobs.
|
|
70
70
|
*/
|
|
71
71
|
export interface CronMetadata {
|
|
72
72
|
/**
|
|
@@ -91,25 +91,25 @@ export interface CronMetadata {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
94
|
-
//
|
|
94
|
+
// Job Store
|
|
95
95
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
|
-
* Complete metadata structure stored on @
|
|
98
|
+
* Complete metadata structure stored on @JobController classes.
|
|
99
99
|
*
|
|
100
100
|
* Accessed via `Store.from(Class).get(MONQUE)`.
|
|
101
101
|
*
|
|
102
102
|
* @example
|
|
103
103
|
* ```typescript
|
|
104
|
-
* const store = Store.from(
|
|
104
|
+
* const store = Store.from(EmailJobs).get<JobStore>(MONQUE);
|
|
105
105
|
* console.log(store.namespace); // "email"
|
|
106
|
-
* console.log(store.
|
|
106
|
+
* console.log(store.jobs); // [{ name: "send", method: "sendEmail", opts: {} }]
|
|
107
107
|
* ```
|
|
108
108
|
*/
|
|
109
|
-
export interface
|
|
109
|
+
export interface JobStore {
|
|
110
110
|
/**
|
|
111
111
|
* Type identifier for the store.
|
|
112
|
-
* Always "controller" for
|
|
112
|
+
* Always "controller" for JobController.
|
|
113
113
|
*/
|
|
114
114
|
type: 'controller';
|
|
115
115
|
|
|
@@ -120,9 +120,9 @@ export interface WorkerStore {
|
|
|
120
120
|
namespace?: string;
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
|
-
*
|
|
123
|
+
* Job method registrations from @Job decorators.
|
|
124
124
|
*/
|
|
125
|
-
|
|
125
|
+
jobs: JobMetadata[];
|
|
126
126
|
|
|
127
127
|
/**
|
|
128
128
|
* Cron job registrations from @Cron decorators.
|
package/src/index.ts
CHANGED
|
@@ -3,18 +3,18 @@ export { MONQUE, type ProviderType, ProviderTypes } from './constants';
|
|
|
3
3
|
export type {
|
|
4
4
|
CronDecoratorOptions,
|
|
5
5
|
CronMetadata,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
JobDecoratorOptions,
|
|
7
|
+
JobMetadata,
|
|
8
|
+
JobStore,
|
|
9
9
|
} from './decorators';
|
|
10
|
-
export { Cron,
|
|
10
|
+
export { Cron, Job, JobController } from './decorators';
|
|
11
11
|
export { MonqueModule } from './monque-module.js';
|
|
12
12
|
export { MonqueService } from './services';
|
|
13
13
|
export {
|
|
14
14
|
buildJobName,
|
|
15
|
-
type
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
type CollectedJobMetadata,
|
|
16
|
+
collectJobMetadata,
|
|
17
|
+
getJobToken,
|
|
18
18
|
type InjectorFn,
|
|
19
19
|
resolveDatabase,
|
|
20
20
|
} from './utils';
|
package/src/monque-module.ts
CHANGED
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
* MonqueModule - Main Integration Module
|
|
3
3
|
*
|
|
4
4
|
* Orchestrates the integration between Monque and Ts.ED.
|
|
5
|
-
* Handles lifecycle hooks, configuration resolution, and
|
|
5
|
+
* Handles lifecycle hooks, configuration resolution, and job registration.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
type Job,
|
|
10
10
|
Monque,
|
|
11
|
+
MonqueError,
|
|
11
12
|
type MonqueOptions,
|
|
12
13
|
type ScheduleOptions,
|
|
13
14
|
type WorkerOptions,
|
|
15
|
+
WorkerRegistrationError,
|
|
14
16
|
} from '@monque/core';
|
|
15
17
|
import {
|
|
16
18
|
Configuration,
|
|
@@ -29,7 +31,7 @@ import {
|
|
|
29
31
|
import { type MonqueTsedConfig, validateDatabaseConfig } from '@/config';
|
|
30
32
|
import { ProviderTypes } from '@/constants';
|
|
31
33
|
import { MonqueService } from '@/services';
|
|
32
|
-
import {
|
|
34
|
+
import { collectJobMetadata, resolveDatabase } from '@/utils';
|
|
33
35
|
|
|
34
36
|
@Module({
|
|
35
37
|
imports: [MonqueService],
|
|
@@ -80,11 +82,13 @@ export class MonqueModule implements OnInit, OnDestroy {
|
|
|
80
82
|
this.logger.info('Monque: Connecting to MongoDB...');
|
|
81
83
|
await this.monque.initialize();
|
|
82
84
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
if (config.disableJobProcessing) {
|
|
86
|
+
this.logger.info('Monque: Job processing is disabled for this instance');
|
|
87
|
+
} else {
|
|
88
|
+
await this.registerJobs();
|
|
89
|
+
await this.monque.start();
|
|
90
|
+
this.logger.info('Monque: Started successfully');
|
|
91
|
+
}
|
|
88
92
|
} catch (error) {
|
|
89
93
|
this.logger.error({
|
|
90
94
|
event: 'MONQUE_INIT_ERROR',
|
|
@@ -107,22 +111,22 @@ export class MonqueModule implements OnInit, OnDestroy {
|
|
|
107
111
|
}
|
|
108
112
|
|
|
109
113
|
/**
|
|
110
|
-
* Discover and register all
|
|
114
|
+
* Discover and register all jobs from @JobController providers
|
|
111
115
|
*/
|
|
112
|
-
protected async
|
|
116
|
+
protected async registerJobs(): Promise<void> {
|
|
113
117
|
if (!this.monque) {
|
|
114
|
-
throw new
|
|
118
|
+
throw new MonqueError('Monque instance not initialized');
|
|
115
119
|
}
|
|
116
120
|
|
|
117
121
|
const monque = this.monque;
|
|
118
|
-
const
|
|
122
|
+
const jobControllers = this.injector.getProviders(ProviderTypes.JOB_CONTROLLER);
|
|
119
123
|
const registeredJobs = new Set<string>();
|
|
120
124
|
|
|
121
|
-
this.logger.info(`Monque: Found ${
|
|
125
|
+
this.logger.info(`Monque: Found ${jobControllers.length} job controllers`);
|
|
122
126
|
|
|
123
|
-
for (const provider of
|
|
127
|
+
for (const provider of jobControllers) {
|
|
124
128
|
const useClass = provider.useClass;
|
|
125
|
-
const
|
|
129
|
+
const jobs = collectJobMetadata(useClass);
|
|
126
130
|
// Try to resolve singleton instance immediately
|
|
127
131
|
const instance = this.injector.get(provider.token);
|
|
128
132
|
|
|
@@ -134,12 +138,13 @@ export class MonqueModule implements OnInit, OnDestroy {
|
|
|
134
138
|
continue;
|
|
135
139
|
}
|
|
136
140
|
|
|
137
|
-
for (const
|
|
138
|
-
const { fullName, method, opts, isCron, cronPattern } =
|
|
141
|
+
for (const job of jobs) {
|
|
142
|
+
const { fullName, method, opts, isCron, cronPattern } = job;
|
|
139
143
|
|
|
140
144
|
if (registeredJobs.has(fullName)) {
|
|
141
|
-
throw new
|
|
145
|
+
throw new WorkerRegistrationError(
|
|
142
146
|
`Monque: Duplicate job registration detected. Job "${fullName}" is already registered.`,
|
|
147
|
+
fullName,
|
|
143
148
|
);
|
|
144
149
|
}
|
|
145
150
|
|
|
@@ -188,7 +193,7 @@ export class MonqueModule implements OnInit, OnDestroy {
|
|
|
188
193
|
monque.register(fullName, handler, opts as WorkerOptions);
|
|
189
194
|
await monque.schedule(cronPattern, fullName, {}, opts as ScheduleOptions);
|
|
190
195
|
} else {
|
|
191
|
-
this.logger.debug(`Monque: Registering
|
|
196
|
+
this.logger.debug(`Monque: Registering job "${fullName}"`);
|
|
192
197
|
monque.register(fullName, handler, opts as WorkerOptions);
|
|
193
198
|
}
|
|
194
199
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Build the full job name by combining namespace and name.
|
|
3
3
|
*
|
|
4
|
-
* @param namespace - Optional namespace from @
|
|
5
|
-
* @param name - Job name from @
|
|
4
|
+
* @param namespace - Optional namespace from @JobController
|
|
5
|
+
* @param name - Job name from @Job or @Cron
|
|
6
6
|
* @returns Full job name (e.g., "email.send" or just "send")
|
|
7
7
|
*
|
|
8
8
|
* @example
|