@wavezync/nestjs-pgboss 1.0.0 → 2.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.
Files changed (37) hide show
  1. package/dist/decorators/job.decorator.d.ts +1 -0
  2. package/dist/decorators/job.decorator.js +4 -1
  3. package/dist/decorators/job.decorator.js.map +1 -1
  4. package/dist/handler-scanner.service.d.ts +11 -0
  5. package/dist/handler-scanner.service.js +66 -0
  6. package/dist/handler-scanner.service.js.map +1 -0
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.js +1 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/interfaces/handler-metadata.interface.d.ts +7 -0
  11. package/dist/interfaces/handler-metadata.interface.js +3 -0
  12. package/dist/interfaces/handler-metadata.interface.js.map +1 -0
  13. package/dist/pgboss.module.d.ts +12 -2
  14. package/dist/pgboss.module.js +51 -10
  15. package/dist/pgboss.module.js.map +1 -1
  16. package/dist/pgboss.service.d.ts +4 -3
  17. package/dist/pgboss.service.js +9 -5
  18. package/dist/pgboss.service.js.map +1 -1
  19. package/dist/utils/consts.d.ts +4 -1
  20. package/dist/utils/consts.js +5 -2
  21. package/dist/utils/consts.js.map +1 -1
  22. package/dist/utils/conversion-helper.d.ts +2 -0
  23. package/dist/utils/conversion-helper.js +7 -0
  24. package/dist/utils/conversion-helper.js.map +1 -0
  25. package/dist/utils/handleRetry.d.ts +1 -0
  26. package/dist/utils/handleRetry.js +15 -0
  27. package/dist/utils/handleRetry.js.map +1 -0
  28. package/lib/decorators/job.decorator.ts +11 -0
  29. package/lib/handler-scanner.service.ts +80 -0
  30. package/lib/index.ts +1 -0
  31. package/lib/interfaces/handler-metadata.interface.ts +8 -0
  32. package/lib/pgboss.module.ts +69 -22
  33. package/lib/pgboss.service.ts +21 -16
  34. package/lib/utils/consts.ts +4 -1
  35. package/lib/utils/conversion-helper.ts +10 -0
  36. package/lib/utils/handleRetry.ts +30 -0
  37. package/package.json +1 -1
@@ -3,5 +3,6 @@ export declare const JOB_NAME = "JOB_NAME";
3
3
  export declare const JOB_OPTIONS = "JOB_OPTIONS";
4
4
  export declare const CRON_EXPRESSION = "CRON_EXPRESSION";
5
5
  export declare const CRON_OPTIONS = "CRON_OPTIONS";
6
+ export declare const PG_BOSS_JOB_METADATA = "PG_BOSS_JOB_METADATA";
6
7
  export declare function Job<_TData extends object = any>(name: string, options?: JobOptions): (target: any, key: string, descriptor: PropertyDescriptor) => void;
7
8
  export declare function CronJob<_TData extends object = any>(name: string, cron: string, options?: JobOptions): (target: any, key: string, descriptor: PropertyDescriptor) => void;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CRON_OPTIONS = exports.CRON_EXPRESSION = exports.JOB_OPTIONS = exports.JOB_NAME = void 0;
3
+ exports.PG_BOSS_JOB_METADATA = exports.CRON_OPTIONS = exports.CRON_EXPRESSION = exports.JOB_OPTIONS = exports.JOB_NAME = void 0;
4
4
  exports.Job = Job;
5
5
  exports.CronJob = CronJob;
6
6
  const common_1 = require("@nestjs/common");
@@ -8,10 +8,12 @@ exports.JOB_NAME = "JOB_NAME";
8
8
  exports.JOB_OPTIONS = "JOB_OPTIONS";
9
9
  exports.CRON_EXPRESSION = "CRON_EXPRESSION";
10
10
  exports.CRON_OPTIONS = "CRON_OPTIONS";
11
+ exports.PG_BOSS_JOB_METADATA = "PG_BOSS_JOB_METADATA";
11
12
  function Job(name, options = {}) {
12
13
  return (target, key, descriptor) => {
13
14
  (0, common_1.SetMetadata)(exports.JOB_NAME, name)(target, key, descriptor);
14
15
  (0, common_1.SetMetadata)(exports.JOB_OPTIONS, options)(target, key, descriptor);
16
+ (0, common_1.SetMetadata)(exports.PG_BOSS_JOB_METADATA, { jobName: name, workOptions: options })(target, key, descriptor);
15
17
  };
16
18
  }
17
19
  function CronJob(name, cron, options = {}) {
@@ -19,6 +21,7 @@ function CronJob(name, cron, options = {}) {
19
21
  (0, common_1.SetMetadata)(exports.JOB_NAME, name)(target, key, descriptor);
20
22
  (0, common_1.SetMetadata)(exports.CRON_EXPRESSION, cron)(target, key, descriptor);
21
23
  (0, common_1.SetMetadata)(exports.CRON_OPTIONS, options)(target, key, descriptor);
24
+ (0, common_1.SetMetadata)(exports.PG_BOSS_JOB_METADATA, { jobName: name, workOptions: options })(target, key, descriptor);
22
25
  };
23
26
  }
24
27
  //# sourceMappingURL=job.decorator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"job.decorator.js","sourceRoot":"","sources":["../../lib/decorators/job.decorator.ts"],"names":[],"mappings":";;;AAQA,kBAQC;AAED,0BAUC;AA5BD,2CAA6C;AAGhC,QAAA,QAAQ,GAAG,UAAU,CAAC;AACtB,QAAA,WAAW,GAAG,aAAa,CAAC;AAC5B,QAAA,eAAe,GAAG,iBAAiB,CAAC;AACpC,QAAA,YAAY,GAAG,cAAc,CAAC;AAE3C,SAAgB,GAAG,CACjB,IAAY,EACZ,UAAsB,EAAE;IAExB,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,UAA8B,EAAE,EAAE;QAClE,IAAA,oBAAW,EAAC,gBAAQ,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QACrD,IAAA,oBAAW,EAAC,mBAAW,EAAE,OAAO,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;IAC7D,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,OAAO,CACrB,IAAY,EACZ,IAAY,EACZ,UAAsB,EAAE;IAExB,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,UAA8B,EAAE,EAAE;QAClE,IAAA,oBAAW,EAAC,gBAAQ,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QACrD,IAAA,oBAAW,EAAC,uBAAe,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QAC5D,IAAA,oBAAW,EAAC,oBAAY,EAAE,OAAO,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;IAC9D,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"job.decorator.js","sourceRoot":"","sources":["../../lib/decorators/job.decorator.ts"],"names":[],"mappings":";;;AASA,kBAaC;AAED,0BAeC;AAvCD,2CAA6C;AAGhC,QAAA,QAAQ,GAAG,UAAU,CAAC;AACtB,QAAA,WAAW,GAAG,aAAa,CAAC;AAC5B,QAAA,eAAe,GAAG,iBAAiB,CAAC;AACpC,QAAA,YAAY,GAAG,cAAc,CAAC;AAC9B,QAAA,oBAAoB,GAAG,sBAAsB,CAAC;AAE3D,SAAgB,GAAG,CACjB,IAAY,EACZ,UAAsB,EAAE;IAExB,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,UAA8B,EAAE,EAAE;QAClE,IAAA,oBAAW,EAAC,gBAAQ,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QACrD,IAAA,oBAAW,EAAC,mBAAW,EAAE,OAAO,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QAC3D,IAAA,oBAAW,EAAC,4BAAoB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CACxE,MAAM,EACN,GAAG,EACH,UAAU,CACX,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,OAAO,CACrB,IAAY,EACZ,IAAY,EACZ,UAAsB,EAAE;IAExB,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,UAA8B,EAAE,EAAE;QAClE,IAAA,oBAAW,EAAC,gBAAQ,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QACrD,IAAA,oBAAW,EAAC,uBAAe,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QAC5D,IAAA,oBAAW,EAAC,oBAAY,EAAE,OAAO,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QAC5D,IAAA,oBAAW,EAAC,4BAAoB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CACxE,MAAM,EACN,GAAG,EACH,UAAU,CACX,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { Reflector, ModulesContainer } from "@nestjs/core";
2
+ import { PgBossService } from "./pgboss.service";
3
+ export declare class HandlerScannerService {
4
+ private readonly pgBossService;
5
+ private readonly reflector;
6
+ private readonly modulesContainer;
7
+ private readonly logger;
8
+ constructor(pgBossService: PgBossService, reflector: Reflector, modulesContainer: ModulesContainer);
9
+ scanAndRegisterHandlers(): Promise<void>;
10
+ private scanProvider;
11
+ }
@@ -0,0 +1,66 @@
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 __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.HandlerScannerService = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const core_1 = require("@nestjs/core");
15
+ const pgboss_service_1 = require("./pgboss.service");
16
+ const job_decorator_1 = require("./decorators/job.decorator");
17
+ const consts_1 = require("./utils/consts");
18
+ let HandlerScannerService = class HandlerScannerService {
19
+ constructor(pgBossService, reflector, modulesContainer) {
20
+ this.pgBossService = pgBossService;
21
+ this.reflector = reflector;
22
+ this.modulesContainer = modulesContainer;
23
+ this.logger = new common_1.Logger(consts_1.LOGGER);
24
+ }
25
+ async scanAndRegisterHandlers() {
26
+ for (const module of this.modulesContainer.values()) {
27
+ const providers = [...module.providers.values()];
28
+ for (const provider of providers) {
29
+ this.scanProvider(provider);
30
+ }
31
+ }
32
+ }
33
+ async scanProvider(provider) {
34
+ const { instance } = provider;
35
+ if (!instance || typeof instance !== "object")
36
+ return;
37
+ const prototype = Object.getPrototypeOf(instance);
38
+ const methodNames = Object.getOwnPropertyNames(prototype).filter((method) => method !== "constructor" && typeof instance[method] === "function");
39
+ for (const methodName of methodNames) {
40
+ const methodRef = instance[methodName];
41
+ const jobName = this.reflector.get(job_decorator_1.JOB_NAME, methodRef);
42
+ const jobOptions = this.reflector.get(job_decorator_1.JOB_OPTIONS, methodRef);
43
+ const cronExpression = this.reflector.get(job_decorator_1.CRON_EXPRESSION, methodRef);
44
+ const cronOptions = this.reflector.get(job_decorator_1.CRON_OPTIONS, methodRef);
45
+ if (jobName) {
46
+ const boundHandler = methodRef.bind(instance);
47
+ if (cronExpression) {
48
+ await this.pgBossService.registerCronJob(jobName, cronExpression, boundHandler, {}, cronOptions);
49
+ this.logger.log(`Registered cron job: ${jobName}`);
50
+ }
51
+ else {
52
+ await this.pgBossService.registerJob(jobName, boundHandler, jobOptions);
53
+ this.logger.log(`Registered job: ${jobName}`);
54
+ }
55
+ }
56
+ }
57
+ }
58
+ };
59
+ exports.HandlerScannerService = HandlerScannerService;
60
+ exports.HandlerScannerService = HandlerScannerService = __decorate([
61
+ (0, common_1.Injectable)(),
62
+ __metadata("design:paramtypes", [pgboss_service_1.PgBossService,
63
+ core_1.Reflector,
64
+ core_1.ModulesContainer])
65
+ ], HandlerScannerService);
66
+ //# sourceMappingURL=handler-scanner.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler-scanner.service.js","sourceRoot":"","sources":["../lib/handler-scanner.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAoD;AACpD,uCAA2D;AAC3D,qDAAiD;AACjD,8DAKoC;AAGpC,2CAAsC;AAG/B,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IAGhC,YACmB,aAA4B,EAC5B,SAAoB,EACpB,gBAAkC;QAFlC,kBAAa,GAAb,aAAa,CAAe;QAC5B,cAAS,GAAT,SAAS,CAAW;QACpB,qBAAgB,GAAhB,gBAAgB,CAAkB;QALpC,WAAM,GAAG,IAAI,eAAM,CAAC,eAAM,CAAC,CAAC;IAM1C,CAAC;IAEJ,KAAK,CAAC,uBAAuB;QAC3B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC;YACpD,MAAM,SAAS,GAAG,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;YAEjD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,QAA8B;QACvD,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC;QAC9B,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,OAAO;QAEtD,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,WAAW,GAAG,MAAM,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,MAAM,CAC9D,CAAC,MAAM,EAAE,EAAE,CACT,MAAM,KAAK,aAAa,IAAI,OAAO,QAAQ,CAAC,MAAM,CAAC,KAAK,UAAU,CACrE,CAAC;QAEF,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,MAAM,SAAS,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;YACvC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAS,wBAAQ,EAAE,SAAS,CAAC,CAAC;YAChE,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CACnC,2BAAW,EACX,SAAS,CACV,CAAC;YACF,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CACvC,+BAAe,EACf,SAAS,CACV,CAAC;YACF,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAM,4BAAY,EAAE,SAAS,CAAC,CAAC;YAErE,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAE9C,IAAI,cAAc,EAAE,CAAC;oBACnB,MAAM,IAAI,CAAC,aAAa,CAAC,eAAe,CACtC,OAAO,EACP,cAAc,EACd,YAAY,EACZ,EAAE,EACF,WAAW,CACZ,CAAC;oBACF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAC;gBACrD,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,CAAC,aAAa,CAAC,WAAW,CAClC,OAAO,EACP,YAAY,EACZ,UAAU,CACX,CAAC;oBACF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,mBAAmB,OAAO,EAAE,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;CACF,CAAA;AAjEY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;qCAKuB,8BAAa;QACjB,gBAAS;QACF,uBAAgB;GAN1C,qBAAqB,CAiEjC"}
package/dist/index.d.ts CHANGED
@@ -2,3 +2,4 @@ export * from "./pgboss.module";
2
2
  export * from "./pgboss.service";
3
3
  export * from "./decorators/job.decorator";
4
4
  export * from "./interfaces/pgboss-module-options.interface";
5
+ export * from "./handler-scanner.service";
package/dist/index.js CHANGED
@@ -18,4 +18,5 @@ __exportStar(require("./pgboss.module"), exports);
18
18
  __exportStar(require("./pgboss.service"), exports);
19
19
  __exportStar(require("./decorators/job.decorator"), exports);
20
20
  __exportStar(require("./interfaces/pgboss-module-options.interface"), exports);
21
+ __exportStar(require("./handler-scanner.service"), exports);
21
22
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,mDAAiC;AACjC,6DAA2C;AAC3C,+EAA6D"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,mDAAiC;AACjC,6DAA2C;AAC3C,+EAA6D;AAC7D,4DAA0C"}
@@ -0,0 +1,7 @@
1
+ import { JobOptions } from "pg-boss";
2
+ export interface HandlerMetadata {
3
+ jobName: string;
4
+ workOptions?: JobOptions;
5
+ cronExpression?: string;
6
+ cronOptions?: JobOptions;
7
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=handler-metadata.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler-metadata.interface.js","sourceRoot":"","sources":["../../lib/interfaces/handler-metadata.interface.ts"],"names":[],"mappings":""}
@@ -1,7 +1,17 @@
1
- import { DynamicModule } from "@nestjs/common";
1
+ import { DynamicModule, OnModuleInit, OnApplicationBootstrap, OnModuleDestroy } from "@nestjs/common";
2
+ import PgBoss from "pg-boss";
2
3
  import { PgBossModuleAsyncOptions } from "./interfaces/pgboss-module-options.interface";
3
- export declare class PgBossModule {
4
+ import { HandlerScannerService } from "./handler-scanner.service";
5
+ export declare class PgBossModule implements OnModuleInit, OnApplicationBootstrap, OnModuleDestroy {
6
+ private readonly boss;
7
+ private readonly handlerScannerService;
8
+ private readonly logger;
9
+ constructor(boss: PgBoss, handlerScannerService: HandlerScannerService);
4
10
  static forRootAsync(options: PgBossModuleAsyncOptions): DynamicModule;
5
11
  private static createAsyncProviders;
6
12
  private static createAsyncOptionsProvider;
13
+ onModuleInit(): void;
14
+ onApplicationBootstrap(): Promise<void>;
15
+ onModuleDestroy(): Promise<void>;
16
+ private setupWorkers;
7
17
  }
@@ -5,6 +5,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
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
6
  return c > 3 && r && Object.defineProperty(target, key, r), r;
7
7
  };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
8
14
  var __importDefault = (this && this.__importDefault) || function (mod) {
9
15
  return (mod && mod.__esModule) ? mod : { "default": mod };
10
16
  };
@@ -12,17 +18,27 @@ var PgBossModule_1;
12
18
  Object.defineProperty(exports, "__esModule", { value: true });
13
19
  exports.PgBossModule = void 0;
14
20
  const common_1 = require("@nestjs/common");
21
+ const core_1 = require("@nestjs/core");
15
22
  const pg_boss_1 = __importDefault(require("pg-boss"));
23
+ const rxjs_1 = require("rxjs");
16
24
  const pgboss_service_1 = require("./pgboss.service");
17
25
  const consts_1 = require("./utils/consts");
26
+ const handler_scanner_service_1 = require("./handler-scanner.service");
27
+ const handleRetry_1 = require("./utils/handleRetry");
18
28
  let PgBossModule = PgBossModule_1 = class PgBossModule {
29
+ constructor(boss, handlerScannerService) {
30
+ this.boss = boss;
31
+ this.handlerScannerService = handlerScannerService;
32
+ this.logger = new common_1.Logger(consts_1.LOGGER);
33
+ }
19
34
  static forRootAsync(options) {
20
- const logger = new common_1.Logger(PgBossModule_1.name);
35
+ const logger = new common_1.Logger(consts_1.LOGGER);
21
36
  const pgBossProvider = {
22
37
  provide: consts_1.PGBOSS_TOKEN,
23
38
  useFactory: async (pgBossOptions) => {
24
- const boss = new pg_boss_1.default(pgBossOptions.connectionString);
25
- await boss.start();
39
+ const boss = await (0, rxjs_1.lastValueFrom)((0, rxjs_1.defer)(() => new pg_boss_1.default({
40
+ connectionString: pgBossOptions.connectionString,
41
+ }).start()).pipe((0, handleRetry_1.handleRetry)(pgBossOptions.retryAttempts, pgBossOptions.retryDelay, pgBossOptions.verboseRetryLog)));
26
42
  logger.log("PgBoss started successfully");
27
43
  return boss;
28
44
  },
@@ -32,8 +48,14 @@ let PgBossModule = PgBossModule_1 = class PgBossModule {
32
48
  return {
33
49
  module: PgBossModule_1,
34
50
  imports: options.imports || [],
35
- providers: [...asyncProviders, pgBossProvider, pgboss_service_1.PgBossService],
36
- exports: [pgboss_service_1.PgBossService],
51
+ providers: [
52
+ ...asyncProviders,
53
+ pgBossProvider,
54
+ pgboss_service_1.PgBossService,
55
+ handler_scanner_service_1.HandlerScannerService,
56
+ core_1.MetadataScanner,
57
+ ],
58
+ exports: [pgboss_service_1.PgBossService, consts_1.PGBOSS_TOKEN],
37
59
  };
38
60
  }
39
61
  static createAsyncProviders(options) {
@@ -43,10 +65,7 @@ let PgBossModule = PgBossModule_1 = class PgBossModule {
43
65
  const useClass = options.useClass;
44
66
  return [
45
67
  this.createAsyncOptionsProvider(options),
46
- {
47
- provide: useClass,
48
- useClass,
49
- },
68
+ { provide: useClass, useClass },
50
69
  ];
51
70
  }
52
71
  static createAsyncOptionsProvider(options) {
@@ -64,10 +83,32 @@ let PgBossModule = PgBossModule_1 = class PgBossModule {
64
83
  inject,
65
84
  };
66
85
  }
86
+ onModuleInit() { }
87
+ async onApplicationBootstrap() {
88
+ await this.setupWorkers();
89
+ }
90
+ async onModuleDestroy() {
91
+ try {
92
+ if (this.boss) {
93
+ await this.boss.stop();
94
+ }
95
+ }
96
+ catch (e) {
97
+ this.logger.error(e);
98
+ }
99
+ }
100
+ async setupWorkers() {
101
+ await this.handlerScannerService.scanAndRegisterHandlers();
102
+ }
67
103
  };
68
104
  exports.PgBossModule = PgBossModule;
69
105
  exports.PgBossModule = PgBossModule = PgBossModule_1 = __decorate([
70
106
  (0, common_1.Global)(),
71
- (0, common_1.Module)({})
107
+ (0, common_1.Module)({
108
+ providers: [core_1.MetadataScanner, handler_scanner_service_1.HandlerScannerService],
109
+ }),
110
+ __param(0, (0, common_1.Inject)(consts_1.PGBOSS_TOKEN)),
111
+ __metadata("design:paramtypes", [pg_boss_1.default,
112
+ handler_scanner_service_1.HandlerScannerService])
72
113
  ], PgBossModule);
73
114
  //# sourceMappingURL=pgboss.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pgboss.module.js","sourceRoot":"","sources":["../lib/pgboss.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;AACA,2CAMwB;AACxB,sDAA6B;AAC7B,qDAAiD;AACjD,2CAA8D;AAQvD,IAAM,YAAY,oBAAlB,MAAM,YAAY;IACvB,MAAM,CAAC,YAAY,CAAC,OAAiC;QACnD,MAAM,MAAM,GAAG,IAAI,eAAM,CAAC,cAAY,CAAC,IAAI,CAAC,CAAC;QAE7C,MAAM,cAAc,GAAa;YAC/B,OAAO,EAAE,qBAAY;YACrB,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE;gBAClC,MAAM,IAAI,GAAG,IAAI,iBAAM,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;gBACxD,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;gBACnB,MAAM,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;gBAC1C,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,EAAE,CAAC,uBAAc,CAAC;SACzB,CAAC;QAEF,MAAM,cAAc,GAAG,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAE1D,OAAO;YACL,MAAM,EAAE,cAAY;YACpB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;YAC9B,SAAS,EAAE,CAAC,GAAG,cAAc,EAAE,cAAc,EAAE,8BAAa,CAAC;YAC7D,OAAO,EAAE,CAAC,8BAAa,CAAC;SACzB,CAAC;IACJ,CAAC;IAEO,MAAM,CAAC,oBAAoB,CACjC,OAAiC;QAEjC,IAAI,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YAC9C,OAAO,CAAC,IAAI,CAAC,0BAA0B,CAAC,OAAO,CAAC,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,QAAQ,GAAG,OAAO,CAAC,QAEA,CAAC;QAE1B,OAAO;YACL,IAAI,CAAC,0BAA0B,CAAC,OAAO,CAAC;YACxC;gBACE,OAAO,EAAE,QAAQ;gBACjB,QAAQ;aACT;SACF,CAAC;IACJ,CAAC;IAEO,MAAM,CAAC,0BAA0B,CACvC,OAAiC;QAEjC,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,OAAO;gBACL,OAAO,EAAE,uBAAc;gBACvB,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;aAC7B,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,WAAW,CAAQ,CAAC,CAAC;QAElE,OAAO;YACL,OAAO,EAAE,uBAAc;YACvB,UAAU,EAAE,KAAK,EAAE,cAAoC,EAAE,EAAE,CACzD,cAAc,CAAC,mBAAmB,EAAE;YACtC,MAAM;SACP,CAAC;IACJ,CAAC;CACF,CAAA;AAjEY,oCAAY;uBAAZ,YAAY;IAFxB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,YAAY,CAiExB"}
1
+ {"version":3,"file":"pgboss.module.js","sourceRoot":"","sources":["../lib/pgboss.module.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
- import PgBoss, { BatchWorkOptions, JobOptions, WorkHandler } from "pg-boss";
1
+ import PgBoss, { BatchWorkOptions, WorkHandler } from "pg-boss";
2
2
  export declare class PgBossService {
3
3
  private readonly boss;
4
4
  constructor(boss: PgBoss);
5
- registerJob<TData extends object>(name: string, handler: WorkHandler<TData>, options?: BatchWorkOptions): Promise<void>;
6
- scheduleJob<TData extends object>(name: string, data: TData, options?: JobOptions): Promise<void>;
5
+ scheduleJob<TData extends object>(name: string, data: TData, options?: PgBoss.SendOptions): Promise<void>;
6
+ scheduleCronJob<TData extends object>(name: string, cron: string, data?: TData, options?: PgBoss.ScheduleOptions): Promise<void>;
7
7
  registerCronJob<TData extends object>(name: string, cron: string, handler: WorkHandler<TData>, data?: TData, options?: PgBoss.ScheduleOptions): Promise<void>;
8
+ registerJob<TData extends object>(name: string, handler: WorkHandler<TData>, options?: BatchWorkOptions): Promise<void>;
8
9
  }
@@ -18,26 +18,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.PgBossService = void 0;
19
19
  const common_1 = require("@nestjs/common");
20
20
  const pg_boss_1 = __importDefault(require("pg-boss"));
21
+ const common_2 = require("@nestjs/common");
21
22
  const consts_1 = require("./utils/consts");
22
23
  let PgBossService = class PgBossService {
23
24
  constructor(boss) {
24
25
  this.boss = boss;
25
26
  }
26
- async registerJob(name, handler, options) {
27
- await this.boss.work(name, options, handler);
28
- }
29
27
  async scheduleJob(name, data, options) {
30
28
  await this.boss.send(name, data, options);
31
29
  }
30
+ async scheduleCronJob(name, cron, data, options) {
31
+ await this.boss.schedule(name, cron, data !== null && data !== void 0 ? data : {}, options !== null && options !== void 0 ? options : {});
32
+ }
32
33
  async registerCronJob(name, cron, handler, data, options) {
33
- await this.boss.schedule(name, cron, data ? data : {}, options ? options : {});
34
+ await this.boss.schedule(name, cron, data !== null && data !== void 0 ? data : {}, options !== null && options !== void 0 ? options : {});
34
35
  await this.boss.work(name, handler);
35
36
  }
37
+ async registerJob(name, handler, options) {
38
+ await this.boss.work(name, options, handler);
39
+ }
36
40
  };
37
41
  exports.PgBossService = PgBossService;
38
42
  exports.PgBossService = PgBossService = __decorate([
39
43
  (0, common_1.Injectable)(),
40
- __param(0, (0, common_1.Inject)(consts_1.PGBOSS_TOKEN)),
44
+ __param(0, (0, common_2.Inject)(consts_1.PGBOSS_TOKEN)),
41
45
  __metadata("design:paramtypes", [pg_boss_1.default])
42
46
  ], PgBossService);
43
47
  //# sourceMappingURL=pgboss.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pgboss.service.js","sourceRoot":"","sources":["../lib/pgboss.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,sDAA4E;AAC5E,2CAA8C;AAGvC,IAAM,aAAa,GAAnB,MAAM,aAAa;IACxB,YAAmD,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAEnE,KAAK,CAAC,WAAW,CACf,IAAY,EACZ,OAA2B,EAC3B,OAA0B;QAE1B,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,WAAW,CACf,IAAY,EACZ,IAAW,EACX,OAAoB;QAEpB,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,IAAY,EACZ,IAAY,EACZ,OAA2B,EAC3B,IAAY,EACZ,OAAgC;QAEhC,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CACtB,IAAI,EACJ,IAAI,EACJ,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAChB,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CACvB,CAAC;QACF,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;CACF,CAAA;AAlCY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;IAEE,WAAA,IAAA,eAAM,EAAC,qBAAY,CAAC,CAAA;qCAAwB,iBAAM;GADpD,aAAa,CAkCzB"}
1
+ {"version":3,"file":"pgboss.service.js","sourceRoot":"","sources":["../lib/pgboss.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,sDAAgE;AAChE,2CAAwC;AACxC,2CAA8C;AAGvC,IAAM,aAAa,GAAnB,MAAM,aAAa;IACxB,YAAmD,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAEnE,KAAK,CAAC,WAAW,CACf,IAAY,EACZ,IAAW,EACX,OAA4B;QAE5B,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,IAAY,EACZ,IAAY,EACZ,IAAY,EACZ,OAAgC;QAEhC,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,EAAE,EAAE,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,IAAY,EACZ,IAAY,EACZ,OAA2B,EAC3B,IAAY,EACZ,OAAgC;QAEhC,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,EAAE,EAAE,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAC,CAAC;QAChE,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,WAAW,CACf,IAAY,EACZ,OAA2B,EAC3B,OAA0B;QAE1B,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;CACF,CAAA;AAtCY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;IAEE,WAAA,IAAA,eAAM,EAAC,qBAAY,CAAC,CAAA;qCAAwB,iBAAM;GADpD,aAAa,CAsCzB"}
@@ -1,2 +1,5 @@
1
+ export declare const PG_BOSS_JOB_METADATA = "PG_BOSS_JOB_METADATA";
2
+ export declare const PGBOSS_TOKEN: unique symbol;
3
+ export declare const MODULE_OPTIONS_TOKEN: unique symbol;
1
4
  export declare const PGBOSS_OPTIONS = "PGBOSS_OPTIONS";
2
- export declare const PGBOSS_TOKEN = "PGBOSS_TOKEN";
5
+ export declare const LOGGER = "nestjs-pgboss";
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PGBOSS_TOKEN = exports.PGBOSS_OPTIONS = void 0;
3
+ exports.LOGGER = exports.PGBOSS_OPTIONS = exports.MODULE_OPTIONS_TOKEN = exports.PGBOSS_TOKEN = exports.PG_BOSS_JOB_METADATA = void 0;
4
+ exports.PG_BOSS_JOB_METADATA = "PG_BOSS_JOB_METADATA";
5
+ exports.PGBOSS_TOKEN = Symbol("PGBOSS_TOKEN");
6
+ exports.MODULE_OPTIONS_TOKEN = Symbol("MODULE_OPTIONS_TOKEN");
4
7
  exports.PGBOSS_OPTIONS = "PGBOSS_OPTIONS";
5
- exports.PGBOSS_TOKEN = "PGBOSS_TOKEN";
8
+ exports.LOGGER = "nestjs-pgboss";
6
9
  //# sourceMappingURL=consts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"consts.js","sourceRoot":"","sources":["../../lib/utils/consts.ts"],"names":[],"mappings":";;;AAAa,QAAA,cAAc,GAAG,gBAAgB,CAAC;AAClC,QAAA,YAAY,GAAG,cAAc,CAAC"}
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../../lib/utils/consts.ts"],"names":[],"mappings":";;;AAAa,QAAA,oBAAoB,GAAG,sBAAsB,CAAC;AAC9C,QAAA,YAAY,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;AACtC,QAAA,oBAAoB,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;AACtD,QAAA,cAAc,GAAG,gBAAgB,CAAC;AAClC,QAAA,MAAM,GAAG,eAAe,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { JobOptions, BatchWorkOptions } from "pg-boss";
2
+ export declare function convertToBatchWorkOptions(jobOptions?: JobOptions): BatchWorkOptions;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertToBatchWorkOptions = convertToBatchWorkOptions;
4
+ function convertToBatchWorkOptions(jobOptions = {}) {
5
+ return Object.assign(Object.assign({}, jobOptions), { batchSize: 1 });
6
+ }
7
+ //# sourceMappingURL=conversion-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversion-helper.js","sourceRoot":"","sources":["../../lib/utils/conversion-helper.ts"],"names":[],"mappings":";;AAEA,8DAOC;AAPD,SAAgB,yBAAyB,CACvC,aAAyB,EAAE;IAE3B,uCACK,UAAU,KACb,SAAS,EAAE,CAAC,IACZ;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function handleRetry(retryAttempts?: number, retryDelay?: number, verbose?: boolean, toRetry?: (err: any) => boolean): <T>(source: import("rxjs").Observable<T>) => import("rxjs").Observable<T>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleRetry = handleRetry;
4
+ const rxjs_1 = require("rxjs");
5
+ const operators_1 = require("rxjs/operators");
6
+ function handleRetry(retryAttempts = 9, retryDelay = 3000, verbose = false, toRetry = (_err) => true) {
7
+ return (source) => source.pipe((0, operators_1.retryWhen)((attempts) => attempts.pipe((0, operators_1.take)(retryAttempts), (0, operators_1.mergeMap)((error, index) => {
8
+ const includeError = toRetry(error);
9
+ if (verbose && includeError) {
10
+ console.warn(`Attempt ${index + 1}: Retrying in ${retryDelay / 1000} seconds...`);
11
+ }
12
+ return includeError ? (0, rxjs_1.of)(error) : (0, rxjs_1.throwError)(error);
13
+ }), (0, operators_1.delay)(retryDelay))));
14
+ }
15
+ //# sourceMappingURL=handleRetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handleRetry.js","sourceRoot":"","sources":["../../lib/utils/handleRetry.ts"],"names":[],"mappings":";;AAGA,kCA0BC;AA7BD,+BAAsC;AACtC,8CAAkE;AAElE,SAAgB,WAAW,CACzB,aAAa,GAAG,CAAC,EACjB,UAAU,GAAG,IAAI,EACjB,OAAO,GAAG,KAAK,EACf,UAAiC,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI;IAEpD,OAAO,CAAI,MAAoC,EAAE,EAAE,CACjD,MAAM,CAAC,IAAI,CACT,IAAA,qBAAS,EAAC,CAAC,QAAQ,EAAE,EAAE,CACrB,QAAQ,CAAC,IAAI,CACX,IAAA,gBAAI,EAAC,aAAa,CAAC,EACnB,IAAA,oBAAQ,EAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACxB,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,OAAO,IAAI,YAAY,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,CACV,WAAW,KAAK,GAAG,CAAC,iBAClB,UAAU,GAAG,IACf,aAAa,CACd,CAAC;QACJ,CAAC;QACD,OAAO,YAAY,CAAC,CAAC,CAAC,IAAA,SAAE,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAA,iBAAU,EAAC,KAAK,CAAC,CAAC;IACtD,CAAC,CAAC,EACF,IAAA,iBAAK,EAAC,UAAU,CAAC,CAClB,CACF,CACF,CAAC;AACN,CAAC"}
@@ -5,6 +5,7 @@ export const JOB_NAME = "JOB_NAME";
5
5
  export const JOB_OPTIONS = "JOB_OPTIONS";
6
6
  export const CRON_EXPRESSION = "CRON_EXPRESSION";
7
7
  export const CRON_OPTIONS = "CRON_OPTIONS";
8
+ export const PG_BOSS_JOB_METADATA = "PG_BOSS_JOB_METADATA";
8
9
 
9
10
  export function Job<_TData extends object = any>(
10
11
  name: string,
@@ -13,6 +14,11 @@ export function Job<_TData extends object = any>(
13
14
  return (target: any, key: string, descriptor: PropertyDescriptor) => {
14
15
  SetMetadata(JOB_NAME, name)(target, key, descriptor);
15
16
  SetMetadata(JOB_OPTIONS, options)(target, key, descriptor);
17
+ SetMetadata(PG_BOSS_JOB_METADATA, { jobName: name, workOptions: options })(
18
+ target,
19
+ key,
20
+ descriptor,
21
+ );
16
22
  };
17
23
  }
18
24
 
@@ -25,5 +31,10 @@ export function CronJob<_TData extends object = any>(
25
31
  SetMetadata(JOB_NAME, name)(target, key, descriptor);
26
32
  SetMetadata(CRON_EXPRESSION, cron)(target, key, descriptor);
27
33
  SetMetadata(CRON_OPTIONS, options)(target, key, descriptor);
34
+ SetMetadata(PG_BOSS_JOB_METADATA, { jobName: name, workOptions: options })(
35
+ target,
36
+ key,
37
+ descriptor,
38
+ );
28
39
  };
29
40
  }
@@ -0,0 +1,80 @@
1
+ import { Injectable, Logger } from "@nestjs/common";
2
+ import { Reflector, ModulesContainer } from "@nestjs/core";
3
+ import { PgBossService } from "./pgboss.service";
4
+ import {
5
+ JOB_NAME,
6
+ JOB_OPTIONS,
7
+ CRON_EXPRESSION,
8
+ CRON_OPTIONS,
9
+ } from "./decorators/job.decorator";
10
+ import { InstanceWrapper } from "@nestjs/core/injector/instance-wrapper";
11
+ import { BatchWorkOptions } from "pg-boss";
12
+ import { LOGGER } from "utils/consts";
13
+
14
+ @Injectable()
15
+ export class HandlerScannerService {
16
+ private readonly logger = new Logger(LOGGER);
17
+
18
+ constructor(
19
+ private readonly pgBossService: PgBossService,
20
+ private readonly reflector: Reflector,
21
+ private readonly modulesContainer: ModulesContainer,
22
+ ) {}
23
+
24
+ async scanAndRegisterHandlers() {
25
+ for (const module of this.modulesContainer.values()) {
26
+ const providers = [...module.providers.values()];
27
+
28
+ for (const provider of providers) {
29
+ this.scanProvider(provider);
30
+ }
31
+ }
32
+ }
33
+
34
+ private async scanProvider(provider: InstanceWrapper<any>) {
35
+ const { instance } = provider;
36
+ if (!instance || typeof instance !== "object") return;
37
+
38
+ const prototype = Object.getPrototypeOf(instance);
39
+ const methodNames = Object.getOwnPropertyNames(prototype).filter(
40
+ (method) =>
41
+ method !== "constructor" && typeof instance[method] === "function",
42
+ );
43
+
44
+ for (const methodName of methodNames) {
45
+ const methodRef = instance[methodName];
46
+ const jobName = this.reflector.get<string>(JOB_NAME, methodRef);
47
+ const jobOptions = this.reflector.get<BatchWorkOptions>(
48
+ JOB_OPTIONS,
49
+ methodRef,
50
+ );
51
+ const cronExpression = this.reflector.get<string>(
52
+ CRON_EXPRESSION,
53
+ methodRef,
54
+ );
55
+ const cronOptions = this.reflector.get<any>(CRON_OPTIONS, methodRef);
56
+
57
+ if (jobName) {
58
+ const boundHandler = methodRef.bind(instance);
59
+
60
+ if (cronExpression) {
61
+ await this.pgBossService.registerCronJob(
62
+ jobName,
63
+ cronExpression,
64
+ boundHandler,
65
+ {},
66
+ cronOptions,
67
+ );
68
+ this.logger.log(`Registered cron job: ${jobName}`);
69
+ } else {
70
+ await this.pgBossService.registerJob(
71
+ jobName,
72
+ boundHandler,
73
+ jobOptions,
74
+ );
75
+ this.logger.log(`Registered job: ${jobName}`);
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
package/lib/index.ts CHANGED
@@ -2,3 +2,4 @@ export * from "./pgboss.module";
2
2
  export * from "./pgboss.service";
3
3
  export * from "./decorators/job.decorator";
4
4
  export * from "./interfaces/pgboss-module-options.interface";
5
+ export * from "./handler-scanner.service";
@@ -0,0 +1,8 @@
1
+ import { JobOptions } from "pg-boss";
2
+
3
+ export interface HandlerMetadata {
4
+ jobName: string;
5
+ workOptions?: JobOptions;
6
+ cronExpression?: string;
7
+ cronOptions?: JobOptions;
8
+ }
@@ -1,30 +1,58 @@
1
- // src/pg-boss.module.ts
2
1
  import {
3
- Module,
4
2
  DynamicModule,
5
3
  Global,
6
- Provider,
7
4
  Logger,
5
+ Module,
6
+ OnModuleInit,
7
+ OnApplicationBootstrap,
8
+ OnModuleDestroy,
9
+ Inject,
8
10
  } from "@nestjs/common";
11
+ import { MetadataScanner } from "@nestjs/core";
9
12
  import PgBoss from "pg-boss";
13
+ import { defer, lastValueFrom } from "rxjs";
10
14
  import { PgBossService } from "./pgboss.service";
11
- import { PGBOSS_OPTIONS, PGBOSS_TOKEN } from "./utils/consts";
15
+ import { LOGGER, PGBOSS_OPTIONS, PGBOSS_TOKEN } from "./utils/consts";
12
16
  import {
13
17
  PgBossModuleAsyncOptions,
14
18
  PgBossOptionsFactory,
15
19
  } from "./interfaces/pgboss-module-options.interface";
20
+ import { HandlerScannerService } from "./handler-scanner.service";
21
+ import { handleRetry } from "utils/handleRetry";
16
22
 
17
23
  @Global()
18
- @Module({})
19
- export class PgBossModule {
24
+ @Module({
25
+ providers: [MetadataScanner, HandlerScannerService],
26
+ })
27
+ export class PgBossModule
28
+ implements OnModuleInit, OnApplicationBootstrap, OnModuleDestroy
29
+ {
30
+ private readonly logger = new Logger(LOGGER);
31
+
32
+ constructor(
33
+ @Inject(PGBOSS_TOKEN) private readonly boss: PgBoss,
34
+ private readonly handlerScannerService: HandlerScannerService,
35
+ ) {}
36
+
20
37
  static forRootAsync(options: PgBossModuleAsyncOptions): DynamicModule {
21
- const logger = new Logger(PgBossModule.name);
38
+ const logger = new Logger(LOGGER);
22
39
 
23
- const pgBossProvider: Provider = {
40
+ const pgBossProvider = {
24
41
  provide: PGBOSS_TOKEN,
25
42
  useFactory: async (pgBossOptions) => {
26
- const boss = new PgBoss(pgBossOptions.connectionString);
27
- await boss.start();
43
+ const boss = await lastValueFrom(
44
+ defer(() =>
45
+ new PgBoss({
46
+ connectionString: pgBossOptions.connectionString,
47
+ }).start(),
48
+ ).pipe(
49
+ handleRetry(
50
+ pgBossOptions.retryAttempts,
51
+ pgBossOptions.retryDelay,
52
+ pgBossOptions.verboseRetryLog,
53
+ ),
54
+ ),
55
+ );
28
56
  logger.log("PgBoss started successfully");
29
57
  return boss;
30
58
  },
@@ -36,14 +64,18 @@ export class PgBossModule {
36
64
  return {
37
65
  module: PgBossModule,
38
66
  imports: options.imports || [],
39
- providers: [...asyncProviders, pgBossProvider, PgBossService],
40
- exports: [PgBossService],
67
+ providers: [
68
+ ...asyncProviders,
69
+ pgBossProvider,
70
+ PgBossService,
71
+ HandlerScannerService,
72
+ MetadataScanner,
73
+ ],
74
+ exports: [PgBossService, PGBOSS_TOKEN],
41
75
  };
42
76
  }
43
77
 
44
- private static createAsyncProviders(
45
- options: PgBossModuleAsyncOptions,
46
- ): Provider[] {
78
+ private static createAsyncProviders(options: PgBossModuleAsyncOptions) {
47
79
  if (options.useExisting || options.useFactory) {
48
80
  return [this.createAsyncOptionsProvider(options)];
49
81
  }
@@ -54,16 +86,11 @@ export class PgBossModule {
54
86
 
55
87
  return [
56
88
  this.createAsyncOptionsProvider(options),
57
- {
58
- provide: useClass,
59
- useClass,
60
- },
89
+ { provide: useClass, useClass },
61
90
  ];
62
91
  }
63
92
 
64
- private static createAsyncOptionsProvider(
65
- options: PgBossModuleAsyncOptions,
66
- ): Provider {
93
+ private static createAsyncOptionsProvider(options: PgBossModuleAsyncOptions) {
67
94
  if (options.useFactory) {
68
95
  return {
69
96
  provide: PGBOSS_OPTIONS,
@@ -81,4 +108,24 @@ export class PgBossModule {
81
108
  inject,
82
109
  };
83
110
  }
111
+
112
+ onModuleInit() {}
113
+
114
+ async onApplicationBootstrap(): Promise<void> {
115
+ await this.setupWorkers();
116
+ }
117
+
118
+ async onModuleDestroy(): Promise<void> {
119
+ try {
120
+ if (this.boss) {
121
+ await this.boss.stop();
122
+ }
123
+ } catch (e) {
124
+ this.logger.error(e);
125
+ }
126
+ }
127
+
128
+ private async setupWorkers() {
129
+ await this.handlerScannerService.scanAndRegisterHandlers();
130
+ }
84
131
  }
@@ -1,25 +1,27 @@
1
- import { Inject, Injectable } from "@nestjs/common";
2
- import PgBoss, { BatchWorkOptions, JobOptions, WorkHandler } from "pg-boss";
1
+ import { Injectable } from "@nestjs/common";
2
+ import PgBoss, { BatchWorkOptions, WorkHandler } from "pg-boss";
3
+ import { Inject } from "@nestjs/common";
3
4
  import { PGBOSS_TOKEN } from "./utils/consts";
4
5
 
5
6
  @Injectable()
6
7
  export class PgBossService {
7
8
  constructor(@Inject(PGBOSS_TOKEN) private readonly boss: PgBoss) {}
8
9
 
9
- async registerJob<TData extends object>(
10
+ async scheduleJob<TData extends object>(
10
11
  name: string,
11
- handler: WorkHandler<TData>,
12
- options?: BatchWorkOptions,
12
+ data: TData,
13
+ options?: PgBoss.SendOptions,
13
14
  ) {
14
- await this.boss.work(name, options, handler);
15
+ await this.boss.send(name, data, options);
15
16
  }
16
17
 
17
- async scheduleJob<TData extends object>(
18
+ async scheduleCronJob<TData extends object>(
18
19
  name: string,
19
- data: TData,
20
- options?: JobOptions,
20
+ cron: string,
21
+ data?: TData,
22
+ options?: PgBoss.ScheduleOptions,
21
23
  ) {
22
- await this.boss.send(name, data, options);
24
+ await this.boss.schedule(name, cron, data ?? {}, options ?? {});
23
25
  }
24
26
 
25
27
  async registerCronJob<TData extends object>(
@@ -29,12 +31,15 @@ export class PgBossService {
29
31
  data?: TData,
30
32
  options?: PgBoss.ScheduleOptions,
31
33
  ) {
32
- await this.boss.schedule(
33
- name,
34
- cron,
35
- data ? data : {},
36
- options ? options : {},
37
- );
34
+ await this.boss.schedule(name, cron, data ?? {}, options ?? {});
38
35
  await this.boss.work(name, handler);
39
36
  }
37
+
38
+ async registerJob<TData extends object>(
39
+ name: string,
40
+ handler: WorkHandler<TData>,
41
+ options?: BatchWorkOptions,
42
+ ) {
43
+ await this.boss.work(name, options, handler);
44
+ }
40
45
  }
@@ -1,2 +1,5 @@
1
+ export const PG_BOSS_JOB_METADATA = "PG_BOSS_JOB_METADATA";
2
+ export const PGBOSS_TOKEN = Symbol("PGBOSS_TOKEN");
3
+ export const MODULE_OPTIONS_TOKEN = Symbol("MODULE_OPTIONS_TOKEN");
1
4
  export const PGBOSS_OPTIONS = "PGBOSS_OPTIONS";
2
- export const PGBOSS_TOKEN = "PGBOSS_TOKEN";
5
+ export const LOGGER = "nestjs-pgboss";
@@ -0,0 +1,10 @@
1
+ import { JobOptions, BatchWorkOptions } from "pg-boss";
2
+
3
+ export function convertToBatchWorkOptions(
4
+ jobOptions: JobOptions = {},
5
+ ): BatchWorkOptions {
6
+ return {
7
+ ...jobOptions,
8
+ batchSize: 1,
9
+ };
10
+ }
@@ -0,0 +1,30 @@
1
+ import { of, throwError } from "rxjs";
2
+ import { mergeMap, retryWhen, take, delay } from "rxjs/operators";
3
+
4
+ export function handleRetry(
5
+ retryAttempts = 9,
6
+ retryDelay = 3000,
7
+ verbose = false,
8
+ toRetry: (err: any) => boolean = (_err: any) => true,
9
+ ) {
10
+ return <T>(source: import("rxjs").Observable<T>) =>
11
+ source.pipe(
12
+ retryWhen((attempts) =>
13
+ attempts.pipe(
14
+ take(retryAttempts),
15
+ mergeMap((error, index) => {
16
+ const includeError = toRetry(error);
17
+ if (verbose && includeError) {
18
+ console.warn(
19
+ `Attempt ${index + 1}: Retrying in ${
20
+ retryDelay / 1000
21
+ } seconds...`,
22
+ );
23
+ }
24
+ return includeError ? of(error) : throwError(error);
25
+ }),
26
+ delay(retryDelay),
27
+ ),
28
+ ),
29
+ );
30
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wavezync/nestjs-pgboss",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "A NestJS module that integrates pg-boss for job scheduling and handling.",
5
5
  "license": "MIT",
6
6
  "author": "samaratungajs@wavezync.com",