@tsed/agenda 8.29.1 → 8.30.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.
@@ -6,7 +6,3 @@ export function JobsController(options) {
6
6
  type: PROVIDER_TYPE_AGENDA
7
7
  }));
8
8
  }
9
- /**
10
- * @deprecated Use `JobsController` instead.
11
- */
12
- export const Agenda = JobsController;
package/lib/esm/index.js CHANGED
@@ -2,9 +2,9 @@
2
2
  * @file Automatically generated by @tsed/barrels.
3
3
  */
4
4
  export * from "./constants/constants.js";
5
- export * from "./decorators/agenda.js";
6
5
  export * from "./decorators/define.js";
7
6
  export * from "./decorators/every.js";
7
+ export * from "./decorators/jobController.js";
8
8
  export * from "./interfaces/AgendaStore.js";
9
9
  export * from "./interfaces/interfaces.js";
10
10
  export * from "./services/AgendaService.js";
@@ -4,7 +4,11 @@ import { Agenda } from "agenda";
4
4
  import { v4 as uuid } from "uuid";
5
5
  import { PROVIDER_TYPE_AGENDA } from "../constants/constants.js";
6
6
  function getOpts() {
7
- return constant("agenda", { enabled: false });
7
+ return constant("agenda", false);
8
+ }
9
+ function getEnabledAgendaOptions(settings) {
10
+ const { enabled, disableJobProcessing, drainJobsBeforeClose, ...agendaOptions } = settings;
11
+ return agendaOptions;
8
12
  }
9
13
  function addAgendaDefinitionsForProvider(agenda, provider) {
10
14
  const store = provider.store.get("agenda", {});
@@ -13,9 +17,11 @@ function addAgendaDefinitionsForProvider(agenda, provider) {
13
17
  }
14
18
  Object.entries(store.define).forEach(([propertyKey, { name, ...options }]) => {
15
19
  const instance = injector().get(provider.token);
16
- const jobProcessor = instance[propertyKey].bind(instance);
20
+ const jobProcessor = async (job) => {
21
+ return Promise.resolve(instance[propertyKey].call(instance, job));
22
+ };
17
23
  const jobName = getNameForJob(propertyKey, store.namespace, name);
18
- agenda.define(jobName, options, jobProcessor);
24
+ agenda.define(jobName, jobProcessor, options);
19
25
  });
20
26
  }
21
27
  async function scheduleJobsForProvider(agenda, provider) {
@@ -35,7 +41,7 @@ function getNameForJob(propertyKey, namespace, customName) {
35
41
  }
36
42
  async function afterListen(agenda) {
37
43
  const opts = getOpts();
38
- if (opts.enabled) {
44
+ if (opts && opts.enabled) {
39
45
  const providers = injector().getProviders(PROVIDER_TYPE_AGENDA);
40
46
  if (!opts.disableJobProcessing) {
41
47
  logger().info({
@@ -58,7 +64,7 @@ async function afterListen(agenda) {
58
64
  }
59
65
  async function onDestroy(agenda) {
60
66
  const opts = getOpts();
61
- if (opts.enabled) {
67
+ if (opts && opts.enabled) {
62
68
  if (opts.drainJobsBeforeClose && "drain" in agenda) {
63
69
  logger().info({
64
70
  event: "AGENDA_DRAIN",
@@ -73,15 +79,14 @@ async function onDestroy(agenda) {
73
79
  });
74
80
  await agenda.stop();
75
81
  }
76
- await agenda.close({ force: true });
77
82
  logger().info({ event: "AGENDA_STOP", message: "Agenda stopped" });
78
83
  }
79
84
  }
80
85
  export const AgendaService = injectable(Agenda)
81
86
  .factory(() => {
82
87
  const opts = getOpts();
83
- if (opts.enabled) {
84
- const agenda = new Agenda(opts);
88
+ if (opts && opts.enabled) {
89
+ const agenda = new Agenda(getEnabledAgendaOptions(opts));
85
90
  return new Proxy(agenda, {
86
91
  set(target, prop, value) {
87
92
  return Reflect.set(target, prop, value);
@@ -94,14 +99,14 @@ export const AgendaService = injectable(Agenda)
94
99
  return Reflect.get(target, "define", target);
95
100
  }
96
101
  if (prop === "define") {
97
- return (name, options, processor) => {
98
- return target["define"](name, options, (job) => {
102
+ return (name, processor, options) => {
103
+ return target["define"](name, async (job) => {
99
104
  const $ctx = new DIContext({
100
105
  id: uuid()
101
106
  });
102
107
  $ctx.set("job", job);
103
- return runInContext($ctx, () => processor(job));
104
- });
108
+ return Promise.resolve(runInContext($ctx, () => processor(job)));
109
+ }, options);
105
110
  };
106
111
  }
107
112
  return Reflect.get(target, prop, target);
@@ -115,7 +120,3 @@ export const AgendaService = injectable(Agenda)
115
120
  $onDestroy: onDestroy
116
121
  })
117
122
  .token();
118
- /**
119
- * @deprecated Use `Agenda` from `agenda` instead.
120
- */
121
- export const AgendaModule = Agenda;
@@ -2,8 +2,4 @@ interface AgendaOptions {
2
2
  namespace?: string;
3
3
  }
4
4
  export declare function JobsController(options?: AgendaOptions): any;
5
- /**
6
- * @deprecated Use `JobsController` instead.
7
- */
8
- export declare const Agenda: typeof JobsController;
9
5
  export {};
@@ -2,9 +2,9 @@
2
2
  * @file Automatically generated by @tsed/barrels.
3
3
  */
4
4
  export * from "./constants/constants.js";
5
- export * from "./decorators/agenda.js";
6
5
  export * from "./decorators/define.js";
7
6
  export * from "./decorators/every.js";
7
+ export * from "./decorators/jobController.js";
8
8
  export * from "./interfaces/AgendaStore.js";
9
9
  export * from "./interfaces/interfaces.js";
10
10
  export * from "./services/AgendaService.js";
@@ -1,8 +1,16 @@
1
- import { DefineOptions as AgendaDefineOptions, JobOptions } from "agenda";
2
- export interface DefineOptions extends AgendaDefineOptions {
1
+ import { type JobDefinition } from "agenda";
2
+ type AgendaJobOptions = {
3
+ timezone?: string;
4
+ skipImmediate?: boolean;
5
+ forkMode?: boolean;
6
+ startDate?: Date | string;
7
+ endDate?: Date | string;
8
+ skipDays?: number[];
9
+ };
10
+ export interface DefineOptions extends Partial<Pick<JobDefinition, "lockLimit" | "lockLifetime" | "concurrency" | "backoff" | "removeOnComplete" | "logging" | "priority">> {
3
11
  name?: string;
4
12
  }
5
- export type EveryOptions = JobOptions & DefineOptions;
13
+ export type EveryOptions = AgendaJobOptions & DefineOptions;
6
14
  export interface AgendaStore {
7
15
  namespace?: string;
8
16
  define?: {
@@ -14,3 +22,4 @@ export interface AgendaStore {
14
22
  };
15
23
  };
16
24
  }
25
+ export {};
@@ -1,9 +1,13 @@
1
- import { AgendaConfig } from "agenda";
2
- export type AgendaSettings = AgendaConfig & {
3
- enabled?: boolean;
1
+ import { type AgendaOptions } from "agenda";
2
+ type CommonSettings = {
4
3
  disableJobProcessing?: boolean;
5
4
  drainJobsBeforeClose?: boolean;
6
- };
5
+ } & AgendaOptions;
6
+ export type AgendaSettings = ({
7
+ enabled: false;
8
+ } & Partial<CommonSettings>) | ({
9
+ enabled?: true;
10
+ } & CommonSettings);
7
11
  declare global {
8
12
  namespace TsED {
9
13
  interface Configuration {
@@ -11,3 +15,4 @@ declare global {
11
15
  }
12
16
  }
13
17
  }
18
+ export {};
@@ -6,8 +6,3 @@ export declare const AgendaService: {
6
6
  * @deprecated Use `Agenda` from `agenda` instead.
7
7
  */
8
8
  export type AgendaService = Agenda;
9
- /**
10
- * @deprecated Use `Agenda` from `agenda` instead.
11
- */
12
- export declare const AgendaModule: typeof Agenda;
13
- export type AgendaModule = Agenda;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@tsed/agenda",
3
3
  "description": "Agenda package for Ts.ED framework",
4
4
  "type": "module",
5
- "version": "8.29.1",
5
+ "version": "8.30.0",
6
6
  "source": "./src/index.ts",
7
7
  "main": "./lib/esm/index.js",
8
8
  "module": "./lib/esm/index.js",
@@ -26,18 +26,21 @@
26
26
  "tslib": ">=2.7.0"
27
27
  },
28
28
  "devDependencies": {
29
- "@tsed/barrels": "8.29.1",
30
- "@tsed/core": "8.29.1",
31
- "@tsed/di": "8.29.1",
32
- "@tsed/platform-http": "8.29.1",
33
- "@tsed/typescript": "8.29.1",
34
- "agenda": "^5.0.0",
29
+ "@agendajs/mongo-backend": "^4.0.2",
30
+ "@tsed/barrels": "8.30.0",
31
+ "@tsed/core": "8.30.0",
32
+ "@tsed/di": "8.30.0",
33
+ "@tsed/platform-http": "8.30.0",
34
+ "@tsed/testcontainers-mongo": "8.30.0",
35
+ "@tsed/typescript": "8.30.0",
36
+ "agenda": "^6.2.5",
35
37
  "eslint": "9.12.0",
38
+ "mongodb": "^6.21.0",
36
39
  "typescript": "6.0.2",
37
40
  "vitest": "4.1.4"
38
41
  },
39
42
  "peerDependencies": {
40
- "agenda": ">=4"
43
+ "agenda": "^6.2.5"
41
44
  },
42
45
  "repository": "https://github.com/tsedio/tsed",
43
46
  "bugs": {
package/readme.md CHANGED
@@ -32,7 +32,7 @@ A package of Ts.ED framework. See website: https://tsed.dev
32
32
 
33
33
  ## Feature
34
34
 
35
- Currently, `@tsed/agenda` allows you to decorate classes with `@Agenda` and
35
+ Currently, `@tsed/agenda` allows you to decorate classes with `@JobsController` and
36
36
  corresponding methods to have them picked up by the Agenda library to be
37
37
  scheduled automatically (`@Every`) or programmatically (`@Define`) via the AgendaService.
38
38
 
@@ -43,8 +43,37 @@ For more information about Agenda look at the documentation [here](https://githu
43
43
  To begin, install the Agenda module for Ts.ED:
44
44
 
45
45
  ```bash
46
- npm install --save @tsed/agenda
47
- npm install --save agenda
46
+ npm install --save @tsed/agenda agenda @agendajs/mongo-backend
47
+ ```
48
+
49
+ ## Migration note
50
+
51
+ `@tsed/agenda` now targets Agenda v6.
52
+
53
+ - `agenda.backend` is required when the module is enabled
54
+ - top-level `db`, `mongo`, and `repository` configuration are no longer supported
55
+ - `ensureIndex` and `sort` move into `new MongoBackend(...)`
56
+ - sort directions use `"asc"` / `"desc"` instead of `1` / `-1`
57
+ - `@Agenda()` has been removed in favor of `@JobsController()`
58
+ - `AgendaModule` has been removed; inject `Agenda` from `agenda`
59
+
60
+ ```diff
61
+ import {Configuration} from "@tsed/di";
62
+ import "@tsed/agenda";
63
+ +import {MongoBackend} from "@agendajs/mongo-backend";
64
+
65
+ @Configuration({
66
+ agenda: {
67
+ enabled: true,
68
+ - db: {
69
+ - address: mongoConnectionString
70
+ - }
71
+ + backend: new MongoBackend({
72
+ + address: mongoConnectionString
73
+ + })
74
+ }
75
+ })
76
+ export class Server {}
48
77
  ```
49
78
 
50
79
  ## Configure your server
@@ -54,18 +83,23 @@ Import `@tsed/agenda` in your Server:
54
83
  ```typescript
55
84
  import {Configuration} from "@tsed/di";
56
85
  import "@tsed/agenda"; // import agenda ts.ed module
86
+ import {MongoBackend} from "@agendajs/mongo-backend";
57
87
 
58
88
  const mongoConnectionString = "mongodb://127.0.0.1/agenda";
59
89
 
60
90
  @Configuration({
61
91
  agenda: {
62
92
  enabled: true, // Enable Agenda jobs for this instance.
63
- // drainJobsBeforeStop: true, // Wait for jobs to finish before stopping the agenda process.
93
+ // drainJobsBeforeClose: true, // Wait for jobs to finish before stopping the agenda process.
64
94
  // disableJobProcessing: true, // Prevents jobs from being processed.
65
- // pass any options that you would normally pass to new Agenda(), e.g.
66
- db: {
67
- address: mongoConnectionString
68
- }
95
+ backend: new MongoBackend({
96
+ address: mongoConnectionString,
97
+ ensureIndex: true,
98
+ sort: {
99
+ nextRunAt: "asc",
100
+ priority: "desc"
101
+ }
102
+ })
69
103
  }
70
104
  })
71
105
  export class Server {}
@@ -73,7 +107,7 @@ export class Server {}
73
107
 
74
108
  ## Create a new Service
75
109
 
76
- Decorate the class with `@Agenda`. The `namespace` option is optional and will
110
+ Decorate the class with `@JobsController`. The `namespace` option is optional and will
77
111
  prefix the job name with `namespace.`
78
112
 
79
113
  Use the `@Every` decorator to define a cron-like job that gets automatically
@@ -83,6 +117,22 @@ method name is used as job name.
83
117
  Use the `@Define` decorator on methods that you would like to schedule
84
118
  programmatically via the AgendaService and Agenda instance access.
85
119
 
120
+ ### Migration note for decorators and injection
121
+
122
+ ```diff
123
+ -import {Agenda, AgendaModule, Define, Every} from "@tsed/agenda";
124
+ +import {Define, Every, JobsController} from "@tsed/agenda";
125
+ +import {Agenda} from "agenda";
126
+
127
+ -@Agenda({namespace: "email"})
128
+ +@JobsController({namespace: "email"})
129
+ export class EmailJobService {
130
+ @Inject()
131
+ - agenda: AgendaModule;
132
+ + agenda: Agenda;
133
+ }
134
+ ```
135
+
86
136
  ```ts
87
137
  import {Every, Define, JobsController} from "@tsed/agenda";
88
138
  import {Job} from "agenda";
@@ -114,8 +164,8 @@ export class EmailJobService {
114
164
 
115
165
  ## Define a job processor manually
116
166
 
117
- Since Ts.ED 7.53.0, AgendaModule exposes methods to manually define a job processor. It can be useful to define a job
118
- processor when you need to fetch data beforehand and dynamically build job name / options.
167
+ Inject `Agenda` from `agenda` to manually define a job processor. It can be useful when you need to fetch data
168
+ beforehand and dynamically build job name / options.
119
169
 
120
170
  ```typescript
121
171
  import {Define, JobsController} from "@tsed/agenda";
@@ -162,12 +212,11 @@ export class EmailJobService {
162
212
 
163
213
  ## Inject Agenda
164
214
 
165
- Inject the AgendaService instance to interact with it directly, e.g. to schedule
215
+ Inject the Agenda instance to interact with it directly, e.g. to schedule
166
216
  a job manually.
167
217
 
168
218
  ```ts
169
219
  import {Service} from "@tsed/di";
170
- import {AfterRoutesInit} from "@tsed/platform-params";
171
220
  import {Agenda} from "agenda";
172
221
 
173
222
  @Service()
@@ -200,7 +249,7 @@ This is an optional feature and is not required to use agenda.
200
249
  Install the additional dependency.
201
250
 
202
251
  ```shell
203
- npm install --save agendash
252
+ npm install --save agendash agenda @agendajs/mongo-backend
204
253
  ```
205
254
 
206
255
  Afterward create the module `agendash.module.ts` in src/modules so that the dashboard can be exposed using middleware.
@@ -209,7 +258,7 @@ Afterward create the module `agendash.module.ts` in src/modules so that the dash
209
258
  import {AfterRoutesInit, PlatformApplication} from "@tsed/platform-http";
210
259
  import {Configuration, Inject, Module} from "@tsed/di";
211
260
  import {Agenda} from "agenda";
212
- import Agendash from "agendash";
261
+ import {expressMiddleware} from "agendash";
213
262
 
214
263
  @Module()
215
264
  export class AgendashModule implements AfterRoutesInit {
@@ -224,7 +273,7 @@ export class AgendashModule implements AfterRoutesInit {
224
273
 
225
274
  $afterRoutesInit() {
226
275
  if (this.config.agenda?.enabled) {
227
- this.app.use("/agendash", Agendash(this.agenda));
276
+ this.app.use("/agendash", expressMiddleware(this.agenda));
228
277
  }
229
278
  }
230
279
  }
@@ -249,7 +298,7 @@ website. [[Become a sponsor](https://opencollective.com/tsed#sponsor)]
249
298
 
250
299
  The MIT License (MIT)
251
300
 
252
- Copyright (c) 2016 - 2021 Romain Lenzotti
301
+ Copyright (c) 2016 - Today Romain Lenzotti
253
302
 
254
303
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
255
304
  documentation files (the "Software"), to deal in the Software without restriction, including without limitation the