@monque/tsed 0.1.0 → 1.1.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 +22 -22
- package/dist/CHANGELOG.md +31 -0
- package/dist/README.md +22 -22
- package/dist/index.cjs +105 -91
- 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 +101 -88
- package/dist/index.mjs.map +1 -1
- package/package.json +16 -16
- 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/README.md
CHANGED
|
@@ -26,12 +26,12 @@ A **Ts.ED** integration for **Monque**, a robust, type-safe MongoDB job queue fo
|
|
|
26
26
|
|
|
27
27
|
## Features
|
|
28
28
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
29
|
+
- **Decorator-based API**: `@JobController`, `@Job`, and `@Cron` for declarative job handling.
|
|
30
|
+
- **Dependency Injection**: Full support for Ts.ED DI (inject Services/Providers into your jobs).
|
|
31
|
+
- **Job Isolation**: Each job execution runs in a dedicated `DIContext` with Request Scope support.
|
|
32
|
+
- **Type Safety**: Leverage TypeScript generics for fully typed job payloads.
|
|
33
|
+
- **Full Monque Power**: Complete access to all `@monque/core` features (backoff, heartbeats, atomic locking).
|
|
34
|
+
- **Seamless Integration**: Native lifecycle hooks support (`$onInit`, `$onDestroy`) for graceful scheduler management.
|
|
35
35
|
|
|
36
36
|
## Installation
|
|
37
37
|
|
|
@@ -85,13 +85,13 @@ export class Server {}
|
|
|
85
85
|
|
|
86
86
|
## Usage
|
|
87
87
|
|
|
88
|
-
### 1. Define a
|
|
88
|
+
### 1. Define a Job Controller
|
|
89
89
|
|
|
90
|
-
Create a class decorated with `@
|
|
90
|
+
Create a class decorated with `@JobController`. Methods decorated with `@Job` will process jobs.
|
|
91
91
|
|
|
92
92
|
```typescript
|
|
93
|
-
import {
|
|
94
|
-
import { Job } from "@monque/core";
|
|
93
|
+
import { JobController, Job } from "@monque/tsed";
|
|
94
|
+
import { Job as MonqueJob } from "@monque/core";
|
|
95
95
|
import { EmailService } from "./services/EmailService";
|
|
96
96
|
|
|
97
97
|
interface EmailPayload {
|
|
@@ -99,12 +99,12 @@ interface EmailPayload {
|
|
|
99
99
|
subject: string;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
@
|
|
103
|
-
export class
|
|
102
|
+
@JobController("email") // Namespace prefix: "email."
|
|
103
|
+
export class EmailJobs {
|
|
104
104
|
constructor(private emailService: EmailService) {}
|
|
105
105
|
|
|
106
|
-
@
|
|
107
|
-
async sendEmail(job:
|
|
106
|
+
@Job("send", { concurrency: 5 }) // Job name: "email.send"
|
|
107
|
+
async sendEmail(job: MonqueJob<EmailPayload>) {
|
|
108
108
|
await this.emailService.send(
|
|
109
109
|
job.data.to,
|
|
110
110
|
job.data.subject
|
|
@@ -118,10 +118,10 @@ export class EmailWorkers {
|
|
|
118
118
|
Use the `@Cron` decorator to schedule recurring tasks.
|
|
119
119
|
|
|
120
120
|
```typescript
|
|
121
|
-
import {
|
|
121
|
+
import { JobController, Cron } from "@monque/tsed";
|
|
122
122
|
|
|
123
|
-
@
|
|
124
|
-
export class
|
|
123
|
+
@JobController()
|
|
124
|
+
export class ReportJobs {
|
|
125
125
|
|
|
126
126
|
@Cron("0 0 * * *", { name: "daily-report" })
|
|
127
127
|
async generateDailyReport() {
|
|
@@ -159,11 +159,11 @@ export class AuthService {
|
|
|
159
159
|
|
|
160
160
|
### Decorators
|
|
161
161
|
|
|
162
|
-
#### `@
|
|
163
|
-
Class decorator to register a
|
|
164
|
-
- `namespace`: Optional prefix for all
|
|
162
|
+
#### `@JobController(namespace?: string)`
|
|
163
|
+
Class decorator to register a job controller.
|
|
164
|
+
- `namespace`: Optional prefix for all job names in this class.
|
|
165
165
|
|
|
166
|
-
#### `@
|
|
166
|
+
#### `@Job(name: string, options?: WorkerOptions)`
|
|
167
167
|
Method decorator to register a job handler.
|
|
168
168
|
- `name`: Job name (combined with namespace).
|
|
169
169
|
- `options`: Supports all `@monque/core` [WorkerOptions](../../packages/core/README.md#new-monque-db-options) (concurrency, lockTimeout, etc.).
|
|
@@ -206,7 +206,7 @@ Use `@tsed/platform-http/testing` and `PlatformTest` to test your workers. You c
|
|
|
206
206
|
import { PlatformTest } from "@tsed/platform-http/testing";
|
|
207
207
|
import { MonqueService } from "@monque/tsed";
|
|
208
208
|
|
|
209
|
-
describe("
|
|
209
|
+
describe("EmailJobs", () => {
|
|
210
210
|
beforeEach(PlatformTest.create);
|
|
211
211
|
afterEach(PlatformTest.reset);
|
|
212
212
|
|
package/dist/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @monque/tsed
|
|
2
2
|
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#163](https://github.com/ueberBrot/monque/pull/163) [`2d542f6`](https://github.com/ueberBrot/monque/commit/2d542f6b78a8ff9b39ec06a7a5217a3bf05f3e02) Thanks [@ueberBrot](https://github.com/ueberBrot)! - mongodb (^7.0.0 → ^7.1.0)
|
|
8
|
+
|
|
9
|
+
- [#165](https://github.com/ueberBrot/monque/pull/165) [`a9b258e`](https://github.com/ueberBrot/monque/commit/a9b258e3191d96b6e1b5f75a8d99e014fb8d0853) Thanks [@renovate](https://github.com/apps/renovate)! - chore(deps): update dependencies
|
|
10
|
+
|
|
11
|
+
- @monque/tsed: @tsed/core (^8.24.1 → ^8.25.1)
|
|
12
|
+
- @monque/tsed: @tsed/di (^8.24.1 → ^8.25.1)
|
|
13
|
+
- @monque/tsed: @tsed/mongoose (^8.24.1 → ^8.25.1)
|
|
14
|
+
|
|
15
|
+
## 1.0.0
|
|
16
|
+
|
|
17
|
+
### Major Changes
|
|
18
|
+
|
|
19
|
+
- [#113](https://github.com/ueberBrot/monque/pull/113) [`94a25d0`](https://github.com/ueberBrot/monque/commit/94a25d0f64f394af72c06a5457db5431df996c45) Thanks [@ueberBrot](https://github.com/ueberBrot)! - Rename `@Worker` and `@WorkerController` to `@Job` and `@JobController`.
|
|
20
|
+
|
|
21
|
+
This is a breaking change that aligns the terminology with the core package and general job queue conventions.
|
|
22
|
+
|
|
23
|
+
- Renamed `@Worker` decorator to `@Job`
|
|
24
|
+
- Renamed `@WorkerController` decorator to `@JobController`
|
|
25
|
+
- Renamed internal metadata types and store keys to use "Job" instead of "Worker" (e.g., `JobStore`, `JobMetadata`)
|
|
26
|
+
- Updated logging and constants to reflect the change
|
|
27
|
+
- Added `disableJobProcessing` option to run Ts.ED instances in producer-only mode. When enabled, the instance can enqueue jobs and manage schedules but will not process any jobs.
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- Updated dependencies [[`9b7f44f`](https://github.com/ueberBrot/monque/commit/9b7f44f5c1f6b4aa4215e571189cc03cbaa49865)]:
|
|
32
|
+
- @monque/core@1.2.0
|
|
33
|
+
|
|
3
34
|
## 0.1.0
|
|
4
35
|
|
|
5
36
|
### Minor Changes
|
package/dist/README.md
CHANGED
|
@@ -26,12 +26,12 @@ A **Ts.ED** integration for **Monque**, a robust, type-safe MongoDB job queue fo
|
|
|
26
26
|
|
|
27
27
|
## Features
|
|
28
28
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
29
|
+
- **Decorator-based API**: `@JobController`, `@Job`, and `@Cron` for declarative job handling.
|
|
30
|
+
- **Dependency Injection**: Full support for Ts.ED DI (inject Services/Providers into your jobs).
|
|
31
|
+
- **Job Isolation**: Each job execution runs in a dedicated `DIContext` with Request Scope support.
|
|
32
|
+
- **Type Safety**: Leverage TypeScript generics for fully typed job payloads.
|
|
33
|
+
- **Full Monque Power**: Complete access to all `@monque/core` features (backoff, heartbeats, atomic locking).
|
|
34
|
+
- **Seamless Integration**: Native lifecycle hooks support (`$onInit`, `$onDestroy`) for graceful scheduler management.
|
|
35
35
|
|
|
36
36
|
## Installation
|
|
37
37
|
|
|
@@ -85,13 +85,13 @@ export class Server {}
|
|
|
85
85
|
|
|
86
86
|
## Usage
|
|
87
87
|
|
|
88
|
-
### 1. Define a
|
|
88
|
+
### 1. Define a Job Controller
|
|
89
89
|
|
|
90
|
-
Create a class decorated with `@
|
|
90
|
+
Create a class decorated with `@JobController`. Methods decorated with `@Job` will process jobs.
|
|
91
91
|
|
|
92
92
|
```typescript
|
|
93
|
-
import {
|
|
94
|
-
import { Job } from "@monque/core";
|
|
93
|
+
import { JobController, Job } from "@monque/tsed";
|
|
94
|
+
import { Job as MonqueJob } from "@monque/core";
|
|
95
95
|
import { EmailService } from "./services/EmailService";
|
|
96
96
|
|
|
97
97
|
interface EmailPayload {
|
|
@@ -99,12 +99,12 @@ interface EmailPayload {
|
|
|
99
99
|
subject: string;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
@
|
|
103
|
-
export class
|
|
102
|
+
@JobController("email") // Namespace prefix: "email."
|
|
103
|
+
export class EmailJobs {
|
|
104
104
|
constructor(private emailService: EmailService) {}
|
|
105
105
|
|
|
106
|
-
@
|
|
107
|
-
async sendEmail(job:
|
|
106
|
+
@Job("send", { concurrency: 5 }) // Job name: "email.send"
|
|
107
|
+
async sendEmail(job: MonqueJob<EmailPayload>) {
|
|
108
108
|
await this.emailService.send(
|
|
109
109
|
job.data.to,
|
|
110
110
|
job.data.subject
|
|
@@ -118,10 +118,10 @@ export class EmailWorkers {
|
|
|
118
118
|
Use the `@Cron` decorator to schedule recurring tasks.
|
|
119
119
|
|
|
120
120
|
```typescript
|
|
121
|
-
import {
|
|
121
|
+
import { JobController, Cron } from "@monque/tsed";
|
|
122
122
|
|
|
123
|
-
@
|
|
124
|
-
export class
|
|
123
|
+
@JobController()
|
|
124
|
+
export class ReportJobs {
|
|
125
125
|
|
|
126
126
|
@Cron("0 0 * * *", { name: "daily-report" })
|
|
127
127
|
async generateDailyReport() {
|
|
@@ -159,11 +159,11 @@ export class AuthService {
|
|
|
159
159
|
|
|
160
160
|
### Decorators
|
|
161
161
|
|
|
162
|
-
#### `@
|
|
163
|
-
Class decorator to register a
|
|
164
|
-
- `namespace`: Optional prefix for all
|
|
162
|
+
#### `@JobController(namespace?: string)`
|
|
163
|
+
Class decorator to register a job controller.
|
|
164
|
+
- `namespace`: Optional prefix for all job names in this class.
|
|
165
165
|
|
|
166
|
-
#### `@
|
|
166
|
+
#### `@Job(name: string, options?: WorkerOptions)`
|
|
167
167
|
Method decorator to register a job handler.
|
|
168
168
|
- `name`: Job name (combined with namespace).
|
|
169
169
|
- `options`: Supports all `@monque/core` [WorkerOptions](../../packages/core/README.md#new-monque-db-options) (concurrency, lockTimeout, etc.).
|
|
@@ -206,7 +206,7 @@ Use `@tsed/platform-http/testing` and `PlatformTest` to test your workers. You c
|
|
|
206
206
|
import { PlatformTest } from "@tsed/platform-http/testing";
|
|
207
207
|
import { MonqueService } from "@monque/tsed";
|
|
208
208
|
|
|
209
|
-
describe("
|
|
209
|
+
describe("EmailJobs", () => {
|
|
210
210
|
beforeEach(PlatformTest.create);
|
|
211
211
|
afterEach(PlatformTest.reset);
|
|
212
212
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
let _monque_core = require("@monque/core");
|
|
1
3
|
let _tsed_core = require("@tsed/core");
|
|
2
4
|
let _tsed_di = require("@tsed/di");
|
|
3
|
-
let _monque_core = require("@monque/core");
|
|
4
5
|
let mongodb = require("mongodb");
|
|
5
6
|
|
|
6
7
|
//#region src/config/config.ts
|
|
7
8
|
/**
|
|
9
|
+
* @monque/tsed - Configuration
|
|
10
|
+
*
|
|
11
|
+
* Defines the configuration interface and TsED module augmentation.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
8
14
|
* Validate that exactly one database resolution strategy is provided.
|
|
9
15
|
*
|
|
10
16
|
* @param config - The configuration to validate.
|
|
@@ -23,8 +29,8 @@ function validateDatabaseConfig(config) {
|
|
|
23
29
|
config.dbFactory,
|
|
24
30
|
config.dbToken
|
|
25
31
|
].filter(Boolean);
|
|
26
|
-
if (strategies.length === 0) throw new
|
|
27
|
-
if (strategies.length > 1) throw new
|
|
32
|
+
if (strategies.length === 0) throw new _monque_core.MonqueError("MonqueTsedConfig requires exactly one of 'db', 'dbFactory', or 'dbToken' to be set");
|
|
33
|
+
if (strategies.length > 1) throw new _monque_core.MonqueError("MonqueTsedConfig accepts only one of 'db', 'dbFactory', or 'dbToken' - multiple were provided");
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
//#endregion
|
|
@@ -32,7 +38,7 @@ function validateDatabaseConfig(config) {
|
|
|
32
38
|
/**
|
|
33
39
|
* Symbol used to store decorator metadata on class constructors.
|
|
34
40
|
*
|
|
35
|
-
* Used by @
|
|
41
|
+
* Used by @JobController, @Job, and @Cron decorators to attach
|
|
36
42
|
* metadata that is later collected by MonqueModule during initialization.
|
|
37
43
|
*
|
|
38
44
|
* @example
|
|
@@ -49,13 +55,13 @@ const MONQUE = Symbol.for("monque");
|
|
|
49
55
|
*
|
|
50
56
|
* These constants are used to categorize providers registered with Ts.ED's
|
|
51
57
|
* dependency injection container, enabling MonqueModule to discover and
|
|
52
|
-
* register
|
|
58
|
+
* register jobs automatically.
|
|
53
59
|
*
|
|
54
60
|
* Note: Using string constants with `as const` instead of enums per
|
|
55
61
|
* Constitution guidelines.
|
|
56
62
|
*/
|
|
57
63
|
const ProviderTypes = {
|
|
58
|
-
|
|
64
|
+
JOB_CONTROLLER: "monque:job-controller",
|
|
59
65
|
CRON: "monque:cron"
|
|
60
66
|
};
|
|
61
67
|
|
|
@@ -69,8 +75,8 @@ const ProviderTypes = {
|
|
|
69
75
|
*
|
|
70
76
|
* @example
|
|
71
77
|
* ```typescript
|
|
72
|
-
* @
|
|
73
|
-
* class
|
|
78
|
+
* @JobController()
|
|
79
|
+
* class ReportJobs {
|
|
74
80
|
* @Cron("@daily", { timezone: "UTC" })
|
|
75
81
|
* async generateDailyReport() {
|
|
76
82
|
* // ...
|
|
@@ -91,7 +97,7 @@ function Cron(pattern, options) {
|
|
|
91
97
|
const store = _tsed_core.Store.from(targetConstructor);
|
|
92
98
|
const existing = store.get(MONQUE) || {
|
|
93
99
|
type: "controller",
|
|
94
|
-
|
|
100
|
+
jobs: [],
|
|
95
101
|
cronJobs: []
|
|
96
102
|
};
|
|
97
103
|
const cronJobs = [...existing.cronJobs || [], cronMetadata];
|
|
@@ -103,21 +109,21 @@ function Cron(pattern, options) {
|
|
|
103
109
|
}
|
|
104
110
|
|
|
105
111
|
//#endregion
|
|
106
|
-
//#region src/decorators/
|
|
112
|
+
//#region src/decorators/job.ts
|
|
107
113
|
/**
|
|
108
|
-
* @
|
|
114
|
+
* @Job method decorator
|
|
109
115
|
*
|
|
110
116
|
* Registers a method as a job handler. The method will be called when a job
|
|
111
117
|
* with the matching name is picked up for processing.
|
|
112
118
|
*
|
|
113
119
|
* @param name - Job name (combined with controller namespace if present).
|
|
114
|
-
* @param options -
|
|
120
|
+
* @param options - Job configuration options.
|
|
115
121
|
*
|
|
116
122
|
* @example
|
|
117
123
|
* ```typescript
|
|
118
|
-
* @
|
|
119
|
-
* export class
|
|
120
|
-
* @
|
|
124
|
+
* @JobController("notifications")
|
|
125
|
+
* export class NotificationJobs {
|
|
126
|
+
* @Job("push", { concurrency: 10 })
|
|
121
127
|
* async sendPush(job: Job<PushPayload>) {
|
|
122
128
|
* await pushService.send(job.data);
|
|
123
129
|
* }
|
|
@@ -128,11 +134,11 @@ function Cron(pattern, options) {
|
|
|
128
134
|
* Method decorator that registers a method as a job handler.
|
|
129
135
|
*
|
|
130
136
|
* @param name - The job name (will be prefixed with controller namespace if present)
|
|
131
|
-
* @param options - Optional
|
|
137
|
+
* @param options - Optional job configuration (concurrency, replace, etc.)
|
|
132
138
|
*/
|
|
133
|
-
function
|
|
139
|
+
function Job(name, options) {
|
|
134
140
|
return (target, propertyKey, _descriptor) => {
|
|
135
|
-
const
|
|
141
|
+
const jobMetadata = {
|
|
136
142
|
name,
|
|
137
143
|
method: String(propertyKey),
|
|
138
144
|
opts: options || {}
|
|
@@ -141,58 +147,58 @@ function Worker(name, options) {
|
|
|
141
147
|
const store = _tsed_core.Store.from(targetConstructor);
|
|
142
148
|
const existing = store.get(MONQUE) || {
|
|
143
149
|
type: "controller",
|
|
144
|
-
|
|
150
|
+
jobs: [],
|
|
145
151
|
cronJobs: []
|
|
146
152
|
};
|
|
147
|
-
const
|
|
153
|
+
const jobs = [...existing.jobs || [], jobMetadata];
|
|
148
154
|
store.set(MONQUE, {
|
|
149
155
|
...existing,
|
|
150
|
-
|
|
156
|
+
jobs
|
|
151
157
|
});
|
|
152
158
|
};
|
|
153
159
|
}
|
|
154
160
|
|
|
155
161
|
//#endregion
|
|
156
|
-
//#region src/decorators/
|
|
162
|
+
//#region src/decorators/job-controller.ts
|
|
157
163
|
/**
|
|
158
|
-
* @
|
|
164
|
+
* @JobController class decorator
|
|
159
165
|
*
|
|
160
|
-
* Marks a class as containing
|
|
161
|
-
*
|
|
166
|
+
* Marks a class as containing job methods and registers it with the Ts.ED DI container.
|
|
167
|
+
* Jobs in the class will have their job names prefixed with the namespace.
|
|
162
168
|
*
|
|
163
169
|
* @param namespace - Optional prefix for all job names in this controller.
|
|
164
170
|
* When set, job names become "{namespace}.{name}".
|
|
165
171
|
*
|
|
166
172
|
* @example
|
|
167
173
|
* ```typescript
|
|
168
|
-
* @
|
|
169
|
-
* export class
|
|
170
|
-
* @
|
|
174
|
+
* @JobController("email")
|
|
175
|
+
* export class EmailJobs {
|
|
176
|
+
* @Job("send") // Registered as "email.send"
|
|
171
177
|
* async send(job: Job<EmailPayload>) { }
|
|
172
178
|
* }
|
|
173
179
|
* ```
|
|
174
180
|
*/
|
|
175
181
|
/**
|
|
176
|
-
* Class decorator that registers a class as a
|
|
182
|
+
* Class decorator that registers a class as a job controller.
|
|
177
183
|
*
|
|
178
184
|
* @param namespace - Optional namespace prefix for job names
|
|
179
185
|
*/
|
|
180
|
-
function
|
|
181
|
-
return (0, _tsed_core.useDecorators)((0, _tsed_di.Injectable)({ type: ProviderTypes.
|
|
186
|
+
function JobController(namespace) {
|
|
187
|
+
return (0, _tsed_core.useDecorators)((0, _tsed_di.Injectable)({ type: ProviderTypes.JOB_CONTROLLER }), (target) => {
|
|
182
188
|
const store = _tsed_core.Store.from(target);
|
|
183
189
|
const existing = store.get(MONQUE) || {};
|
|
184
|
-
const
|
|
190
|
+
const jobStore = {
|
|
185
191
|
type: "controller",
|
|
186
192
|
...namespace !== void 0 && { namespace },
|
|
187
|
-
|
|
193
|
+
jobs: existing.jobs || [],
|
|
188
194
|
cronJobs: existing.cronJobs || []
|
|
189
195
|
};
|
|
190
|
-
store.set(MONQUE,
|
|
196
|
+
store.set(MONQUE, jobStore);
|
|
191
197
|
});
|
|
192
198
|
}
|
|
193
199
|
|
|
194
200
|
//#endregion
|
|
195
|
-
//#region \0@oxc-project+runtime@0.
|
|
201
|
+
//#region \0@oxc-project+runtime@0.112.0/helpers/decorate.js
|
|
196
202
|
function __decorate(decorators, target, key, desc) {
|
|
197
203
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
198
204
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -379,8 +385,8 @@ MonqueService = __decorate([(0, _tsed_di.Injectable)()], MonqueService);
|
|
|
379
385
|
/**
|
|
380
386
|
* Build the full job name by combining namespace and name.
|
|
381
387
|
*
|
|
382
|
-
* @param namespace - Optional namespace from @
|
|
383
|
-
* @param name - Job name from @
|
|
388
|
+
* @param namespace - Optional namespace from @JobController
|
|
389
|
+
* @param name - Job name from @Job or @Cron
|
|
384
390
|
* @returns Full job name (e.g., "email.send" or just "send")
|
|
385
391
|
*
|
|
386
392
|
* @example
|
|
@@ -395,22 +401,22 @@ function buildJobName(namespace, name) {
|
|
|
395
401
|
}
|
|
396
402
|
|
|
397
403
|
//#endregion
|
|
398
|
-
//#region src/utils/collect-
|
|
404
|
+
//#region src/utils/collect-job-metadata.ts
|
|
399
405
|
/**
|
|
400
|
-
* Collect
|
|
406
|
+
* Collect job metadata utility
|
|
401
407
|
*
|
|
402
|
-
* Collects all
|
|
403
|
-
* Used by MonqueModule to discover and register all
|
|
408
|
+
* Collects all job metadata from a class decorated with @JobController.
|
|
409
|
+
* Used by MonqueModule to discover and register all jobs.
|
|
404
410
|
*/
|
|
405
411
|
/**
|
|
406
|
-
* Collect all
|
|
412
|
+
* Collect all job metadata from a class.
|
|
407
413
|
*
|
|
408
|
-
* @param target - The class constructor (decorated with @
|
|
409
|
-
* @returns Array of collected
|
|
414
|
+
* @param target - The class constructor (decorated with @JobController)
|
|
415
|
+
* @returns Array of collected job metadata ready for registration
|
|
410
416
|
*
|
|
411
417
|
* @example
|
|
412
418
|
* ```typescript
|
|
413
|
-
* const metadata =
|
|
419
|
+
* const metadata = collectJobMetadata(EmailJobs);
|
|
414
420
|
* // Returns:
|
|
415
421
|
* // [
|
|
416
422
|
* // { fullName: "email.send", method: "sendEmail", opts: {}, isCron: false },
|
|
@@ -418,18 +424,18 @@ function buildJobName(namespace, name) {
|
|
|
418
424
|
* // ]
|
|
419
425
|
* ```
|
|
420
426
|
*/
|
|
421
|
-
function
|
|
422
|
-
const
|
|
423
|
-
if (!
|
|
427
|
+
function collectJobMetadata(target) {
|
|
428
|
+
const jobStore = _tsed_core.Store.from(target).get(MONQUE);
|
|
429
|
+
if (!jobStore) return [];
|
|
424
430
|
const results = [];
|
|
425
|
-
const namespace =
|
|
426
|
-
for (const
|
|
427
|
-
fullName: buildJobName(namespace,
|
|
428
|
-
method:
|
|
429
|
-
opts:
|
|
431
|
+
const namespace = jobStore.namespace;
|
|
432
|
+
for (const job of jobStore.jobs) results.push({
|
|
433
|
+
fullName: buildJobName(namespace, job.name),
|
|
434
|
+
method: job.method,
|
|
435
|
+
opts: job.opts,
|
|
430
436
|
isCron: false
|
|
431
437
|
});
|
|
432
|
-
for (const cron of
|
|
438
|
+
for (const cron of jobStore.cronJobs) results.push({
|
|
433
439
|
fullName: buildJobName(namespace, cron.name),
|
|
434
440
|
method: cron.method,
|
|
435
441
|
opts: cron.opts,
|
|
@@ -440,29 +446,29 @@ function collectWorkerMetadata(target) {
|
|
|
440
446
|
}
|
|
441
447
|
|
|
442
448
|
//#endregion
|
|
443
|
-
//#region src/utils/get-
|
|
449
|
+
//#region src/utils/get-job-token.ts
|
|
444
450
|
/**
|
|
445
|
-
* Generate a unique token for a
|
|
451
|
+
* Generate a unique token for a job controller.
|
|
446
452
|
*
|
|
447
|
-
* Used internally by Ts.ED DI to identify
|
|
453
|
+
* Used internally by Ts.ED DI to identify job controller providers.
|
|
448
454
|
* The token is based on the class name for debugging purposes.
|
|
449
455
|
*
|
|
450
456
|
* @param target - The class constructor
|
|
451
|
-
* @returns A Symbol token unique to this
|
|
457
|
+
* @returns A Symbol token unique to this job controller
|
|
452
458
|
*
|
|
453
459
|
* @example
|
|
454
460
|
* ```typescript
|
|
455
|
-
* @
|
|
456
|
-
* class
|
|
461
|
+
* @JobController("email")
|
|
462
|
+
* class EmailJobs {}
|
|
457
463
|
*
|
|
458
|
-
* const token =
|
|
459
|
-
* // Symbol("monque:
|
|
464
|
+
* const token = getJobToken(EmailJobs);
|
|
465
|
+
* // Symbol("monque:job:EmailJobs")
|
|
460
466
|
* ```
|
|
461
467
|
*/
|
|
462
|
-
function
|
|
468
|
+
function getJobToken(target) {
|
|
463
469
|
const name = target.name?.trim();
|
|
464
|
-
if (!name) throw new
|
|
465
|
-
return Symbol.for(`monque:
|
|
470
|
+
if (!name) throw new _monque_core.MonqueError("Job class must have a non-empty name");
|
|
471
|
+
return Symbol.for(`monque:job:${name}`);
|
|
466
472
|
}
|
|
467
473
|
|
|
468
474
|
//#endregion
|
|
@@ -491,6 +497,11 @@ function isMongooseConnection(value) {
|
|
|
491
497
|
//#endregion
|
|
492
498
|
//#region src/utils/resolve-database.ts
|
|
493
499
|
/**
|
|
500
|
+
* @monque/tsed - Database Resolution Utility
|
|
501
|
+
*
|
|
502
|
+
* Multi-strategy database resolution for flexible MongoDB connection handling.
|
|
503
|
+
*/
|
|
504
|
+
/**
|
|
494
505
|
* Resolve the MongoDB database instance from the configuration.
|
|
495
506
|
*
|
|
496
507
|
* Supports three resolution strategies:
|
|
@@ -527,30 +538,30 @@ async function resolveDatabase(config, injectorFn) {
|
|
|
527
538
|
if (config.db) return config.db;
|
|
528
539
|
if (config.dbFactory) return config.dbFactory();
|
|
529
540
|
if (config.dbToken) {
|
|
530
|
-
if (!injectorFn) throw new
|
|
541
|
+
if (!injectorFn) throw new _monque_core.ConnectionError("MonqueTsedConfig.dbToken requires an injector function to resolve the database");
|
|
531
542
|
const resolved = injectorFn(config.dbToken);
|
|
532
|
-
if (!resolved) throw new
|
|
543
|
+
if (!resolved) throw new _monque_core.ConnectionError(`Could not resolve database from token: ${String(config.dbToken)}. Make sure the provider is registered in the DI container.`);
|
|
533
544
|
if (isMongooseService(resolved)) {
|
|
534
545
|
const connectionId = config.mongooseConnectionId || "default";
|
|
535
546
|
const connection = resolved.get(connectionId);
|
|
536
|
-
if (!connection) throw new
|
|
547
|
+
if (!connection) throw new _monque_core.ConnectionError(`MongooseService resolved from token "${String(config.dbToken)}" returned no connection for ID "${connectionId}". Ensure the connection ID is correct and the connection is established.`);
|
|
537
548
|
if ("db" in connection && connection.db) return connection.db;
|
|
538
549
|
}
|
|
539
550
|
if (isMongooseConnection(resolved)) return resolved.db;
|
|
540
|
-
if (typeof resolved !== "object" || resolved === null || !("collection" in resolved)) throw new
|
|
551
|
+
if (typeof resolved !== "object" || resolved === null || !("collection" in resolved)) throw new _monque_core.ConnectionError(`Resolved value from token "${String(config.dbToken)}" does not appear to be a valid MongoDB Db instance.`);
|
|
541
552
|
return resolved;
|
|
542
553
|
}
|
|
543
|
-
throw new
|
|
554
|
+
throw new _monque_core.ConnectionError("MonqueTsedConfig requires 'db', 'dbFactory', or 'dbToken' to be set");
|
|
544
555
|
}
|
|
545
556
|
|
|
546
557
|
//#endregion
|
|
547
|
-
//#region \0@oxc-project+runtime@0.
|
|
558
|
+
//#region \0@oxc-project+runtime@0.112.0/helpers/decorateMetadata.js
|
|
548
559
|
function __decorateMetadata(k, v) {
|
|
549
560
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
550
561
|
}
|
|
551
562
|
|
|
552
563
|
//#endregion
|
|
553
|
-
//#region \0@oxc-project+runtime@0.
|
|
564
|
+
//#region \0@oxc-project+runtime@0.112.0/helpers/decorateParam.js
|
|
554
565
|
function __decorateParam(paramIndex, decorator) {
|
|
555
566
|
return function(target, key) {
|
|
556
567
|
decorator(target, key, paramIndex);
|
|
@@ -563,7 +574,7 @@ function __decorateParam(paramIndex, decorator) {
|
|
|
563
574
|
* MonqueModule - Main Integration Module
|
|
564
575
|
*
|
|
565
576
|
* Orchestrates the integration between Monque and Ts.ED.
|
|
566
|
-
* Handles lifecycle hooks, configuration resolution, and
|
|
577
|
+
* Handles lifecycle hooks, configuration resolution, and job registration.
|
|
567
578
|
*/
|
|
568
579
|
var _ref, _ref2, _ref3, _ref4;
|
|
569
580
|
let MonqueModule = class MonqueModule {
|
|
@@ -592,9 +603,12 @@ let MonqueModule = class MonqueModule {
|
|
|
592
603
|
this.monqueService._setMonque(this.monque);
|
|
593
604
|
this.logger.info("Monque: Connecting to MongoDB...");
|
|
594
605
|
await this.monque.initialize();
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
606
|
+
if (config.disableJobProcessing) this.logger.info("Monque: Job processing is disabled for this instance");
|
|
607
|
+
else {
|
|
608
|
+
await this.registerJobs();
|
|
609
|
+
await this.monque.start();
|
|
610
|
+
this.logger.info("Monque: Started successfully");
|
|
611
|
+
}
|
|
598
612
|
} catch (error) {
|
|
599
613
|
this.logger.error({
|
|
600
614
|
event: "MONQUE_INIT_ERROR",
|
|
@@ -612,25 +626,25 @@ let MonqueModule = class MonqueModule {
|
|
|
612
626
|
}
|
|
613
627
|
}
|
|
614
628
|
/**
|
|
615
|
-
* Discover and register all
|
|
629
|
+
* Discover and register all jobs from @JobController providers
|
|
616
630
|
*/
|
|
617
|
-
async
|
|
618
|
-
if (!this.monque) throw new
|
|
631
|
+
async registerJobs() {
|
|
632
|
+
if (!this.monque) throw new _monque_core.MonqueError("Monque instance not initialized");
|
|
619
633
|
const monque = this.monque;
|
|
620
|
-
const
|
|
634
|
+
const jobControllers = this.injector.getProviders(ProviderTypes.JOB_CONTROLLER);
|
|
621
635
|
const registeredJobs = /* @__PURE__ */ new Set();
|
|
622
|
-
this.logger.info(`Monque: Found ${
|
|
623
|
-
for (const provider of
|
|
636
|
+
this.logger.info(`Monque: Found ${jobControllers.length} job controllers`);
|
|
637
|
+
for (const provider of jobControllers) {
|
|
624
638
|
const useClass = provider.useClass;
|
|
625
|
-
const
|
|
639
|
+
const jobs = collectJobMetadata(useClass);
|
|
626
640
|
const instance = this.injector.get(provider.token);
|
|
627
641
|
if (!instance && provider.scope !== _tsed_di.ProviderScope.REQUEST) {
|
|
628
642
|
this.logger.warn(`Monque: Could not resolve instance for controller ${provider.name}. Skipping.`);
|
|
629
643
|
continue;
|
|
630
644
|
}
|
|
631
|
-
for (const
|
|
632
|
-
const { fullName, method, opts, isCron, cronPattern } =
|
|
633
|
-
if (registeredJobs.has(fullName)) throw new
|
|
645
|
+
for (const job of jobs) {
|
|
646
|
+
const { fullName, method, opts, isCron, cronPattern } = job;
|
|
647
|
+
if (registeredJobs.has(fullName)) throw new _monque_core.WorkerRegistrationError(`Monque: Duplicate job registration detected. Job "${fullName}" is already registered.`, fullName);
|
|
634
648
|
registeredJobs.add(fullName);
|
|
635
649
|
const handler = async (job) => {
|
|
636
650
|
const $ctx = new _tsed_di.DIContext({
|
|
@@ -664,7 +678,7 @@ let MonqueModule = class MonqueModule {
|
|
|
664
678
|
monque.register(fullName, handler, opts);
|
|
665
679
|
await monque.schedule(cronPattern, fullName, {}, opts);
|
|
666
680
|
} else {
|
|
667
|
-
this.logger.debug(`Monque: Registering
|
|
681
|
+
this.logger.debug(`Monque: Registering job "${fullName}"`);
|
|
668
682
|
monque.register(fullName, handler, opts);
|
|
669
683
|
}
|
|
670
684
|
}
|
|
@@ -688,6 +702,8 @@ MonqueModule = __decorate([
|
|
|
688
702
|
|
|
689
703
|
//#endregion
|
|
690
704
|
exports.Cron = Cron;
|
|
705
|
+
exports.Job = Job;
|
|
706
|
+
exports.JobController = JobController;
|
|
691
707
|
exports.MONQUE = MONQUE;
|
|
692
708
|
Object.defineProperty(exports, 'MonqueModule', {
|
|
693
709
|
enumerable: true,
|
|
@@ -702,11 +718,9 @@ Object.defineProperty(exports, 'MonqueService', {
|
|
|
702
718
|
}
|
|
703
719
|
});
|
|
704
720
|
exports.ProviderTypes = ProviderTypes;
|
|
705
|
-
exports.Worker = Worker;
|
|
706
|
-
exports.WorkerController = WorkerController;
|
|
707
721
|
exports.buildJobName = buildJobName;
|
|
708
|
-
exports.
|
|
709
|
-
exports.
|
|
722
|
+
exports.collectJobMetadata = collectJobMetadata;
|
|
723
|
+
exports.getJobToken = getJobToken;
|
|
710
724
|
exports.resolveDatabase = resolveDatabase;
|
|
711
725
|
exports.validateDatabaseConfig = validateDatabaseConfig;
|
|
712
726
|
//# sourceMappingURL=index.cjs.map
|