@modern-admin/queue 0.6.0 → 0.9.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 (50) hide show
  1. package/README.md +33 -0
  2. package/dist/cron/cron.constants.d.ts +1 -1
  3. package/dist/cron/cron.constants.js +1 -1
  4. package/dist/cron/cron.processor.d.ts +1 -1
  5. package/dist/cron/cron.processor.d.ts.map +1 -1
  6. package/dist/cron/cron.processor.js +2 -1
  7. package/dist/cron/cron.processor.js.map +1 -1
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +1 -0
  11. package/dist/index.js.map +1 -1
  12. package/dist/queue.module.d.ts +1 -0
  13. package/dist/queue.module.d.ts.map +1 -1
  14. package/dist/queue.module.js +3 -2
  15. package/dist/queue.module.js.map +1 -1
  16. package/dist/retention/index.d.ts +6 -0
  17. package/dist/retention/index.d.ts.map +1 -0
  18. package/dist/retention/index.js +5 -0
  19. package/dist/retention/index.js.map +1 -0
  20. package/dist/retention/retention.constants.d.ts +3 -0
  21. package/dist/retention/retention.constants.d.ts.map +1 -0
  22. package/dist/retention/retention.constants.js +3 -0
  23. package/dist/retention/retention.constants.js.map +1 -0
  24. package/dist/retention/retention.module.d.ts +10 -0
  25. package/dist/retention/retention.module.d.ts.map +1 -0
  26. package/dist/retention/retention.module.js +50 -0
  27. package/dist/retention/retention.module.js.map +1 -0
  28. package/dist/retention/retention.service.d.ts +15 -0
  29. package/dist/retention/retention.service.d.ts.map +1 -0
  30. package/dist/retention/retention.service.js +91 -0
  31. package/dist/retention/retention.service.js.map +1 -0
  32. package/dist/retention/retention.tokens.d.ts +2 -0
  33. package/dist/retention/retention.tokens.d.ts.map +1 -0
  34. package/dist/retention/retention.tokens.js +2 -0
  35. package/dist/retention/retention.tokens.js.map +1 -0
  36. package/dist/retention/retention.types.d.ts +26 -0
  37. package/dist/retention/retention.types.d.ts.map +1 -0
  38. package/dist/retention/retention.types.js +2 -0
  39. package/dist/retention/retention.types.js.map +1 -0
  40. package/package.json +4 -1
  41. package/src/cron/cron.constants.ts +1 -1
  42. package/src/cron/cron.processor.ts +1 -1
  43. package/src/index.ts +13 -0
  44. package/src/queue.module.ts +6 -2
  45. package/src/retention/index.ts +11 -0
  46. package/src/retention/retention.constants.ts +2 -0
  47. package/src/retention/retention.module.ts +42 -0
  48. package/src/retention/retention.service.ts +91 -0
  49. package/src/retention/retention.tokens.ts +1 -0
  50. package/src/retention/retention.types.ts +30 -0
package/README.md CHANGED
@@ -20,6 +20,39 @@ bun add @modern-admin/queue
20
20
  Setup guides, architecture, and usage examples live in the
21
21
  [Modern Admin README](https://github.com/modern-admin/modern-admin#readme).
22
22
 
23
+ ## System retention
24
+
25
+ `RetentionModule` runs history and audit-log pruning in the existing BullMQ
26
+ cron queue. Import `QueueModule.forRoot()` once, then configure whichever
27
+ stores need retention:
28
+
29
+ ```ts
30
+ import { QueueModule, RetentionModule } from '@modern-admin/queue'
31
+
32
+ @Module({
33
+ imports: [
34
+ QueueModule.forRoot({ connection: process.env.REDIS_URL! }),
35
+ RetentionModule.forRoot({
36
+ cron: '0 3 * * *',
37
+ history: {
38
+ store: system.historyStore,
39
+ keepDays: 90,
40
+ keepLast: 100,
41
+ },
42
+ auditLog: {
43
+ store: system.logStore,
44
+ keepDays: 365,
45
+ },
46
+ }),
47
+ ],
48
+ })
49
+ export class AppModule {}
50
+ ```
51
+
52
+ The task uses the cron worker's distributed lock, retries failures three
53
+ times, and does not run when no `keepDays`/`keepLast` bound is configured.
54
+ History `keepLast` is per record; audit-log `keepLast` is global.
55
+
23
56
  ## License
24
57
 
25
58
  [MIT](https://github.com/modern-admin/modern-admin/blob/main/LICENSE) © Modern Admin
@@ -1,4 +1,4 @@
1
- export declare const CRON_QUEUE = "ma:cron";
1
+ export declare const CRON_QUEUE = "ma-cron";
2
2
  export declare const DEFAULT_CRON_WORKER_CONCURRENCY = 4;
3
3
  export declare const CRON_LOCK_PREFIX = "ma:cron-lock:";
4
4
  export declare const DEFAULT_CRON_LOCK_TTL = 300;
@@ -1,4 +1,4 @@
1
- export const CRON_QUEUE = 'ma:cron';
1
+ export const CRON_QUEUE = 'ma-cron';
2
2
  export const DEFAULT_CRON_WORKER_CONCURRENCY = 4;
3
3
  export const CRON_LOCK_PREFIX = 'ma:cron-lock:';
4
4
  export const DEFAULT_CRON_LOCK_TTL = 300;
@@ -1,6 +1,6 @@
1
1
  import { WorkerHost } from '@nestjs/bullmq';
2
2
  import type { Job, Queue } from 'bullmq';
3
- import type { CronService } from './cron.service.js';
3
+ import { CronService } from './cron.service.js';
4
4
  export declare class CronProcessor extends WorkerHost {
5
5
  private readonly cronService;
6
6
  private readonly cronQueue;
@@ -1 +1 @@
1
- {"version":3,"file":"cron.processor.d.ts","sourceRoot":"","sources":["../../src/cron/cron.processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAEnE,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAOxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD,qBACa,aAAc,SAAQ,UAAU;IAIzC,OAAO,CAAC,QAAQ,CAAC,WAAW;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;IAExD,YACmB,WAAW,EAAE,WAAW,EACC,SAAS,EAAE,KAAK,EAG3D;IAEK,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAWlE;YAEa,eAAe;YAmCf,cAAc;CAe7B"}
1
+ {"version":3,"file":"cron.processor.d.ts","sourceRoot":"","sources":["../../src/cron/cron.processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAEnE,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAOxC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,qBACa,aAAc,SAAQ,UAAU;IAIzC,OAAO,CAAC,QAAQ,CAAC,WAAW;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;IAExD,YACmB,WAAW,EAAE,WAAW,EACC,SAAS,EAAE,KAAK,EAG3D;IAEK,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAWlE;YAEa,eAAe;YAmCf,cAAc;CAe7B"}
@@ -14,6 +14,7 @@ var CronProcessor_1;
14
14
  import { InjectQueue, Processor, WorkerHost } from '@nestjs/bullmq';
15
15
  import { Logger } from '@nestjs/common';
16
16
  import { CRON_LOCK_PREFIX, CRON_QUEUE, DEFAULT_CRON_LOCK_TTL, DEFAULT_CRON_WORKER_CONCURRENCY, } from './cron.constants.js';
17
+ import { CronService } from './cron.service.js';
17
18
  let CronProcessor = CronProcessor_1 = class CronProcessor extends WorkerHost {
18
19
  constructor(cronService, cronQueue) {
19
20
  super();
@@ -77,7 +78,7 @@ let CronProcessor = CronProcessor_1 = class CronProcessor extends WorkerHost {
77
78
  CronProcessor = CronProcessor_1 = __decorate([
78
79
  Processor(CRON_QUEUE, { concurrency: DEFAULT_CRON_WORKER_CONCURRENCY }),
79
80
  __param(1, InjectQueue(CRON_QUEUE)),
80
- __metadata("design:paramtypes", [Function, Function])
81
+ __metadata("design:paramtypes", [CronService, Function])
81
82
  ], CronProcessor);
82
83
  export { CronProcessor };
83
84
  //# sourceMappingURL=cron.processor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cron.processor.js","sourceRoot":"","sources":["../../src/cron/cron.processor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cron.processor.js","sourceRoot":"","sources":["../../src/cron/cron.processor.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { QueueModule } from './queue.module.js';
2
2
  export type { QueueModuleOptions, QueueRootOptions } from './queue.types.js';
3
3
  export { CronModule, CronService, CronProcessor, CronTask, CRON_TASK_META, CRON_QUEUE, CRON_LOCK_PREFIX, DEFAULT_CRON_WORKER_CONCURRENCY, DEFAULT_CRON_LOCK_TTL, type CronTaskOptions, type CronHandler, type CronTaskDefinition, } from './cron';
4
+ export { RetentionModule, RetentionService, RETENTION_OPTIONS, DEFAULT_RETENTION_CRON, SYSTEM_RETENTION_TASK, type AuditLogRetentionTarget, type HistoryRetentionTarget, type PrunableStore, type RetentionModuleOptions, type RetentionRunResult, } from './retention';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAE5E,OAAO,EACL,UAAU,EACV,WAAW,EACX,aAAa,EACb,QAAQ,EACR,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,+BAA+B,EAC/B,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,kBAAkB,GACxB,MAAM,QAAQ,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAE5E,OAAO,EACL,UAAU,EACV,WAAW,EACX,aAAa,EACb,QAAQ,EACR,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,+BAA+B,EAC/B,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,kBAAkB,GACxB,MAAM,QAAQ,CAAA;AAEf,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAA"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // @modern-admin/queue — BullMQ queue + cron scheduling for NestJS.
2
2
  export { QueueModule } from './queue.module.js';
3
3
  export { CronModule, CronService, CronProcessor, CronTask, CRON_TASK_META, CRON_QUEUE, CRON_LOCK_PREFIX, DEFAULT_CRON_WORKER_CONCURRENCY, DEFAULT_CRON_LOCK_TTL, } from './cron';
4
+ export { RetentionModule, RetentionService, RETENTION_OPTIONS, DEFAULT_RETENTION_CRON, SYSTEM_RETENTION_TASK, } from './retention';
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mEAAmE;AAEnE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAG/C,OAAO,EACL,UAAU,EACV,WAAW,EACX,aAAa,EACb,QAAQ,EACR,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,+BAA+B,EAC/B,qBAAqB,GAItB,MAAM,QAAQ,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mEAAmE;AAEnE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAG/C,OAAO,EACL,UAAU,EACV,WAAW,EACX,aAAa,EACb,QAAQ,EACR,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,+BAA+B,EAC/B,qBAAqB,GAItB,MAAM,QAAQ,CAAA;AAEf,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,GAMtB,MAAM,aAAa,CAAA"}
@@ -1,5 +1,6 @@
1
1
  import { type DynamicModule } from '@nestjs/common';
2
2
  import type { QueueModuleOptions, QueueRootOptions } from './queue.types.js';
3
+ export declare const normalizeQueueConnection: (connection: QueueRootOptions['connection']) => object;
3
4
  /**
4
5
  * BullMQ integration module for modern-admin NestJS applications.
5
6
  *
@@ -1 +1 @@
1
- {"version":3,"file":"queue.module.d.ts","sourceRoot":"","sources":["../src/queue.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAU,MAAM,gBAAgB,CAAA;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAE5E;;;;;;;;;;;;;;;GAeG;AACH,qBACa,WAAW;IACtB;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa,CAWvD;IAED;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE;QACxB,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAA;QAClC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAA;QAClB,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;KACjF,GAAG,aAAa,CAkBhB;IAED;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,GAAG,aAAa,CAY1D;CACF"}
1
+ {"version":3,"file":"queue.module.d.ts","sourceRoot":"","sources":["../src/queue.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAU,MAAM,gBAAgB,CAAA;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAE5E,eAAO,MAAM,wBAAwB,eACvB,gBAAgB,CAAC,YAAY,CAAC,KACzC,MAA2E,CAAA;AAE9E;;;;;;;;;;;;;;;GAeG;AACH,qBACa,WAAW;IACtB;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa,CAWvD;IAED;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE;QACxB,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAA;QAClC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAA;QAClB,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;KACjF,GAAG,aAAa,CAkBhB;IAED;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,GAAG,aAAa,CAY1D;CACF"}
@@ -7,6 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var QueueModule_1;
8
8
  import { Module } from '@nestjs/common';
9
9
  import { BullModule } from '@nestjs/bullmq';
10
+ export const normalizeQueueConnection = (connection) => typeof connection === 'string' ? { url: connection } : connection;
10
11
  /**
11
12
  * BullMQ integration module for modern-admin NestJS applications.
12
13
  *
@@ -34,7 +35,7 @@ let QueueModule = QueueModule_1 = class QueueModule {
34
35
  global: true,
35
36
  imports: [
36
37
  BullModule.forRoot({
37
- connection: options.connection,
38
+ connection: normalizeQueueConnection(options.connection),
38
39
  defaultJobOptions: options.defaultJobOptions,
39
40
  }),
40
41
  ],
@@ -64,7 +65,7 @@ let QueueModule = QueueModule_1 = class QueueModule {
64
65
  useFactory: async (...args) => {
65
66
  const resolved = await opts.useFactory(...args);
66
67
  return {
67
- connection: resolved.connection,
68
+ connection: normalizeQueueConnection(resolved.connection),
68
69
  defaultJobOptions: resolved.defaultJobOptions,
69
70
  };
70
71
  },
@@ -1 +1 @@
1
- {"version":3,"file":"queue.module.js","sourceRoot":"","sources":["../src/queue.module.ts"],"names":[],"mappings":";;;;;;;AAAA,OAAO,EAAsB,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAG3C;;;;;;;;;;;;;;;GAeG;AAEI,IAAM,WAAW,mBAAjB,MAAM,WAAW;IACtB;;;OAGG;IACI,AAAP,MAAM,CAAC,OAAO,CAAC,OAAyB;QACtC,OAAO;YACL,MAAM,eAAa;YACnB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE;gBACP,UAAU,CAAC,OAAO,CAAC;oBACjB,UAAU,EAAE,OAAO,CAAC,UAAoB;oBACxC,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;iBAC7C,CAAC;aACH;SACF,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,AAAP,MAAM,CAAC,YAAY,CAAC,IAInB;QACC,OAAO;YACL,MAAM,eAAa;YACnB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE;gBACP,UAAU,CAAC,YAAY,CAAC;oBACtB,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,MAAM,EAAE,IAAI,CAAC,MAAiB;oBAC9B,UAAU,EAAE,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;wBACvC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAA;wBAC/C,OAAO;4BACL,UAAU,EAAE,QAAQ,CAAC,UAAoB;4BACzC,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;yBAC9C,CAAA;oBACH,CAAC;iBACF,CAAC;aACH;SACF,CAAA;IACH,CAAC;IAED;;;OAGG;IACI,AAAP,MAAM,CAAC,QAAQ,CAAC,OAA2B;QACzC,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC/C,UAAU,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,CACnC,CAAA;QACD,MAAM,WAAW,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACrD,UAAU,CAAC,oBAAoB,CAAC,EAAE,IAAI,EAAE,CAAC,CAC1C,CAAA;QACD,OAAO;YACL,MAAM,eAAa;YACnB,OAAO,EAAE,CAAC,GAAG,YAAY,EAAE,GAAG,WAAW,CAAC;YAC1C,OAAO,EAAE,CAAC,GAAG,YAAY,EAAE,GAAG,WAAW,CAAC;SAC3C,CAAA;IACH,CAAC;CACF,CAAA;AAxEY,WAAW;IADvB,MAAM,CAAC,EAAE,CAAC;GACE,WAAW,CAwEvB"}
1
+ {"version":3,"file":"queue.module.js","sourceRoot":"","sources":["../src/queue.module.ts"],"names":[],"mappings":";;;;;;;AAAA,OAAO,EAAsB,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAG3C,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,UAA0C,EAClC,EAAE,CAAC,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,UAAU,CAAA;AAE9E;;;;;;;;;;;;;;;GAeG;AAEI,IAAM,WAAW,mBAAjB,MAAM,WAAW;IACtB;;;OAGG;IACI,AAAP,MAAM,CAAC,OAAO,CAAC,OAAyB;QACtC,OAAO;YACL,MAAM,eAAa;YACnB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE;gBACP,UAAU,CAAC,OAAO,CAAC;oBACjB,UAAU,EAAE,wBAAwB,CAAC,OAAO,CAAC,UAAU,CAAC;oBACxD,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;iBAC7C,CAAC;aACH;SACF,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,AAAP,MAAM,CAAC,YAAY,CAAC,IAInB;QACC,OAAO;YACL,MAAM,eAAa;YACnB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE;gBACP,UAAU,CAAC,YAAY,CAAC;oBACtB,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,MAAM,EAAE,IAAI,CAAC,MAAiB;oBAC9B,UAAU,EAAE,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;wBACvC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAA;wBAC/C,OAAO;4BACL,UAAU,EAAE,wBAAwB,CAAC,QAAQ,CAAC,UAAU,CAAC;4BACzD,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;yBAC9C,CAAA;oBACH,CAAC;iBACF,CAAC;aACH;SACF,CAAA;IACH,CAAC;IAED;;;OAGG;IACI,AAAP,MAAM,CAAC,QAAQ,CAAC,OAA2B;QACzC,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC/C,UAAU,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,CACnC,CAAA;QACD,MAAM,WAAW,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACrD,UAAU,CAAC,oBAAoB,CAAC,EAAE,IAAI,EAAE,CAAC,CAC1C,CAAA;QACD,OAAO;YACL,MAAM,eAAa;YACnB,OAAO,EAAE,CAAC,GAAG,YAAY,EAAE,GAAG,WAAW,CAAC;YAC1C,OAAO,EAAE,CAAC,GAAG,YAAY,EAAE,GAAG,WAAW,CAAC;SAC3C,CAAA;IACH,CAAC;CACF,CAAA;AAxEY,WAAW;IADvB,MAAM,CAAC,EAAE,CAAC;GACE,WAAW,CAwEvB"}
@@ -0,0 +1,6 @@
1
+ export { RetentionModule } from './retention.module.js';
2
+ export { RetentionService } from './retention.service.js';
3
+ export { RETENTION_OPTIONS } from './retention.tokens.js';
4
+ export { DEFAULT_RETENTION_CRON, SYSTEM_RETENTION_TASK } from './retention.constants.js';
5
+ export type { AuditLogRetentionTarget, HistoryRetentionTarget, PrunableStore, RetentionModuleOptions, RetentionRunResult, } from './retention.types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/retention/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AACxF,YAAY,EACV,uBAAuB,EACvB,sBAAsB,EACtB,aAAa,EACb,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,sBAAsB,CAAA"}
@@ -0,0 +1,5 @@
1
+ export { RetentionModule } from './retention.module.js';
2
+ export { RetentionService } from './retention.service.js';
3
+ export { RETENTION_OPTIONS } from './retention.tokens.js';
4
+ export { DEFAULT_RETENTION_CRON, SYSTEM_RETENTION_TASK } from './retention.constants.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/retention/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA"}
@@ -0,0 +1,3 @@
1
+ export declare const SYSTEM_RETENTION_TASK = "ma:system-retention";
2
+ export declare const DEFAULT_RETENTION_CRON = "0 3 * * *";
3
+ //# sourceMappingURL=retention.constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.constants.d.ts","sourceRoot":"","sources":["../../src/retention/retention.constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,wBAAwB,CAAA;AAC1D,eAAO,MAAM,sBAAsB,cAAc,CAAA"}
@@ -0,0 +1,3 @@
1
+ export const SYSTEM_RETENTION_TASK = 'ma:system-retention';
2
+ export const DEFAULT_RETENTION_CRON = '0 3 * * *';
3
+ //# sourceMappingURL=retention.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.constants.js","sourceRoot":"","sources":["../../src/retention/retention.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG,qBAAqB,CAAA;AAC1D,MAAM,CAAC,MAAM,sBAAsB,GAAG,WAAW,CAAA"}
@@ -0,0 +1,10 @@
1
+ import { type DynamicModule } from '@nestjs/common';
2
+ import type { RetentionModuleOptions } from './retention.types.js';
3
+ /**
4
+ * Schedules history and action-log pruning as a durable BullMQ cron task.
5
+ * Requires `QueueModule.forRoot()` in the host application's root module.
6
+ */
7
+ export declare class RetentionModule {
8
+ static forRoot(options: RetentionModuleOptions): DynamicModule;
9
+ }
10
+ //# sourceMappingURL=retention.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.module.d.ts","sourceRoot":"","sources":["../../src/retention/retention.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAU,MAAM,gBAAgB,CAAA;AAI3D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAmBlE;;;GAGG;AACH,qBACa,eAAe;IAC1B,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,sBAAsB,GAAG,aAAa,CAW7D;CACF"}
@@ -0,0 +1,50 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var RetentionModule_1;
8
+ import { Module } from '@nestjs/common';
9
+ import { CronModule } from '../cron/cron.module.js';
10
+ import { RetentionService } from './retention.service.js';
11
+ import { RETENTION_OPTIONS } from './retention.tokens.js';
12
+ const assertBound = (name, value) => {
13
+ if (value === undefined)
14
+ return;
15
+ if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {
16
+ throw new Error(`${name} must be a non-negative integer`);
17
+ }
18
+ };
19
+ const validateOptions = (options) => {
20
+ if (options.cron !== undefined && options.cron.trim().length === 0) {
21
+ throw new Error('retention cron must not be empty');
22
+ }
23
+ assertBound('history.keepLast', options.history?.keepLast);
24
+ assertBound('history.keepDays', options.history?.keepDays);
25
+ assertBound('auditLog.keepLast', options.auditLog?.keepLast);
26
+ assertBound('auditLog.keepDays', options.auditLog?.keepDays);
27
+ };
28
+ /**
29
+ * Schedules history and action-log pruning as a durable BullMQ cron task.
30
+ * Requires `QueueModule.forRoot()` in the host application's root module.
31
+ */
32
+ let RetentionModule = RetentionModule_1 = class RetentionModule {
33
+ static forRoot(options) {
34
+ validateOptions(options);
35
+ return {
36
+ module: RetentionModule_1,
37
+ imports: [CronModule],
38
+ providers: [
39
+ { provide: RETENTION_OPTIONS, useValue: options },
40
+ RetentionService,
41
+ ],
42
+ exports: [RetentionService],
43
+ };
44
+ }
45
+ };
46
+ RetentionModule = RetentionModule_1 = __decorate([
47
+ Module({})
48
+ ], RetentionModule);
49
+ export { RetentionModule };
50
+ //# sourceMappingURL=retention.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.module.js","sourceRoot":"","sources":["../../src/retention/retention.module.ts"],"names":[],"mappings":";;;;;;;AAAA,OAAO,EAAsB,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAGzD,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,KAAyB,EAAQ,EAAE;IACpE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAM;IAC/B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,iCAAiC,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC,CAAA;AAED,MAAM,eAAe,GAAG,CAAC,OAA+B,EAAQ,EAAE;IAChE,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;IACrD,CAAC;IACD,WAAW,CAAC,kBAAkB,EAAE,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IAC1D,WAAW,CAAC,kBAAkB,EAAE,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IAC1D,WAAW,CAAC,mBAAmB,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAC5D,WAAW,CAAC,mBAAmB,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;AAC9D,CAAC,CAAA;AAED;;;GAGG;AAEI,IAAM,eAAe,uBAArB,MAAM,eAAe;IACnB,AAAP,MAAM,CAAC,OAAO,CAAC,OAA+B;QAC5C,eAAe,CAAC,OAAO,CAAC,CAAA;QACxB,OAAO;YACL,MAAM,mBAAiB;YACvB,OAAO,EAAE,CAAC,UAAU,CAAC;YACrB,SAAS,EAAE;gBACT,EAAE,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,OAAO,EAAE;gBACjD,gBAAgB;aACjB;YACD,OAAO,EAAE,CAAC,gBAAgB,CAAC;SAC5B,CAAA;IACH,CAAC;CACF,CAAA;AAbY,eAAe;IAD3B,MAAM,CAAC,EAAE,CAAC;GACE,eAAe,CAa3B"}
@@ -0,0 +1,15 @@
1
+ import { type OnModuleInit } from '@nestjs/common';
2
+ import { CronService } from '../cron/cron.service.js';
3
+ import type { RetentionModuleOptions, RetentionRunResult } from './retention.types.js';
4
+ export declare class RetentionService implements OnModuleInit {
5
+ private readonly options;
6
+ private readonly cron;
7
+ constructor(options: RetentionModuleOptions, cron: CronService);
8
+ onModuleInit(): void;
9
+ /** Execute every configured retention target. Called by the BullMQ worker. */
10
+ run(): Promise<RetentionRunResult>;
11
+ private hasWork;
12
+ private pruneHistory;
13
+ private pruneAuditLog;
14
+ }
15
+ //# sourceMappingURL=retention.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.service.d.ts","sourceRoot":"","sources":["../../src/retention/retention.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAEtE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAGrD,OAAO,KAAK,EAGV,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,sBAAsB,CAAA;AAK7B,qBACa,gBAAiB,YAAW,YAAY;IAEtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACnD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFvB,YAC8C,OAAO,EAAE,sBAAsB,EAC1D,IAAI,EAAE,WAAW,EAChC;IAEJ,YAAY,IAAI,IAAI,CAcnB;IAED,8EAA8E;IACxE,GAAG,IAAI,OAAO,CAAC,kBAAkB,CAAC,CA2BvC;IAED,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,aAAa;CAOtB"}
@@ -0,0 +1,91 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { Inject, Injectable } from '@nestjs/common';
14
+ import { CronService } from '../cron/cron.service.js';
15
+ import { DEFAULT_RETENTION_CRON, SYSTEM_RETENTION_TASK } from './retention.constants.js';
16
+ import { RETENTION_OPTIONS } from './retention.tokens.js';
17
+ const hasBounds = (retention) => retention.keepLast !== undefined || retention.keepDays !== undefined;
18
+ let RetentionService = class RetentionService {
19
+ constructor(options, cron) {
20
+ this.options = options;
21
+ this.cron = cron;
22
+ }
23
+ onModuleInit() {
24
+ if (!this.hasWork())
25
+ return;
26
+ this.cron.register({
27
+ name: SYSTEM_RETENTION_TASK,
28
+ cron: this.options.cron ?? DEFAULT_RETENTION_CRON,
29
+ skipIfRunning: true,
30
+ opts: {
31
+ attempts: 3,
32
+ backoff: { type: 'exponential', delay: 1_000 },
33
+ ...this.options.jobOptions,
34
+ },
35
+ handler: () => this.run(),
36
+ });
37
+ }
38
+ /** Execute every configured retention target. Called by the BullMQ worker. */
39
+ async run() {
40
+ const result = {};
41
+ const failures = [];
42
+ if (this.options.history && hasBounds(this.options.history)) {
43
+ try {
44
+ result.history = await this.pruneHistory(this.options.history);
45
+ }
46
+ catch (err) {
47
+ failures.push(err);
48
+ }
49
+ }
50
+ if (this.options.auditLog && hasBounds(this.options.auditLog)) {
51
+ try {
52
+ result.auditLog = await this.pruneAuditLog(this.options.auditLog);
53
+ }
54
+ catch (err) {
55
+ failures.push(err);
56
+ }
57
+ }
58
+ if (failures.length === 1) {
59
+ throw failures[0];
60
+ }
61
+ if (failures.length > 1) {
62
+ throw new AggregateError(failures, 'Multiple retention targets failed');
63
+ }
64
+ return result;
65
+ }
66
+ hasWork() {
67
+ return Boolean((this.options.history && hasBounds(this.options.history))
68
+ || (this.options.auditLog && hasBounds(this.options.auditLog)));
69
+ }
70
+ pruneHistory(target) {
71
+ const retention = {
72
+ ...(target.keepLast !== undefined ? { keepLast: target.keepLast } : {}),
73
+ ...(target.keepDays !== undefined ? { keepDays: target.keepDays } : {}),
74
+ };
75
+ return target.store.prune(retention);
76
+ }
77
+ pruneAuditLog(target) {
78
+ const retention = {
79
+ ...(target.keepLast !== undefined ? { keepLast: target.keepLast } : {}),
80
+ ...(target.keepDays !== undefined ? { keepDays: target.keepDays } : {}),
81
+ };
82
+ return target.store.prune(retention);
83
+ }
84
+ };
85
+ RetentionService = __decorate([
86
+ Injectable(),
87
+ __param(0, Inject(RETENTION_OPTIONS)),
88
+ __metadata("design:paramtypes", [Object, CronService])
89
+ ], RetentionService);
90
+ export { RetentionService };
91
+ //# sourceMappingURL=retention.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.service.js","sourceRoot":"","sources":["../../src/retention/retention.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAqB,MAAM,gBAAgB,CAAA;AAEtE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAQzD,MAAM,SAAS,GAAG,CAAC,SAAmD,EAAW,EAAE,CACjF,SAAS,CAAC,QAAQ,KAAK,SAAS,IAAI,SAAS,CAAC,QAAQ,KAAK,SAAS,CAAA;AAG/D,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAC3B,YAC8C,OAA+B,EAC1D,IAAiB;uBADU,OAAO;oBAClC,IAAI;IACpB,CAAC;IAEJ,YAAY;QACV,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YAAE,OAAM;QAE3B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;YACjB,IAAI,EAAE,qBAAqB;YAC3B,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,sBAAsB;YACjD,aAAa,EAAE,IAAI;YACnB,IAAI,EAAE;gBACJ,QAAQ,EAAE,CAAC;gBACX,OAAO,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE;gBAC9C,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU;aAC3B;YACD,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;SAC1B,CAAC,CAAA;IACJ,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAC,GAAG;QACP,MAAM,MAAM,GAAuB,EAAE,CAAA;QACrC,MAAM,QAAQ,GAAc,EAAE,CAAA;QAE9B,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5D,IAAI,CAAC;gBACH,MAAM,CAAC,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;YAChE,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACpB,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9D,IAAI,CAAC;gBACH,MAAM,CAAC,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;YACnE,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACpB,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,QAAQ,CAAC,CAAC,CAAC,CAAA;QACnB,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,cAAc,CAAC,QAAQ,EAAE,mCAAmC,CAAC,CAAA;QACzE,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;IAEO,OAAO;QACb,OAAO,OAAO,CACZ,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;eACtD,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAC/D,CAAA;IACH,CAAC;IAEO,YAAY,CAAC,MAA8B;QACjD,MAAM,SAAS,GAAqB;YAClC,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvE,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxE,CAAA;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IACtC,CAAC;IAEO,aAAa,CAAC,MAA+B;QACnD,MAAM,SAAS,GAAuB;YACpC,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvE,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxE,CAAA;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IACtC,CAAC;CACF,CAAA;AA1EY,gBAAgB;IAD5B,UAAU,EAAE;IAGR,WAAA,MAAM,CAAC,iBAAiB,CAAC,CAAA;6CACH,WAAW;GAHzB,gBAAgB,CA0E5B"}
@@ -0,0 +1,2 @@
1
+ export declare const RETENTION_OPTIONS: unique symbol;
2
+ //# sourceMappingURL=retention.tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.tokens.d.ts","sourceRoot":"","sources":["../../src/retention/retention.tokens.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,eAAqD,CAAA"}
@@ -0,0 +1,2 @@
1
+ export const RETENTION_OPTIONS = Symbol.for('@modern-admin/queue:RetentionOptions');
2
+ //# sourceMappingURL=retention.tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.tokens.js","sourceRoot":"","sources":["../../src/retention/retention.tokens.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAA"}
@@ -0,0 +1,26 @@
1
+ import type { ActionLogRetention, HistoryRetention } from '@modern-admin/core';
2
+ import type { JobsOptions } from 'bullmq';
3
+ export interface PrunableStore<TRetention> {
4
+ prune(retention: TRetention): Promise<number>;
5
+ }
6
+ export interface HistoryRetentionTarget extends HistoryRetention {
7
+ store: PrunableStore<HistoryRetention>;
8
+ }
9
+ export interface AuditLogRetentionTarget extends ActionLogRetention {
10
+ store: PrunableStore<ActionLogRetention>;
11
+ }
12
+ export interface RetentionModuleOptions {
13
+ /** BullMQ cron expression. Defaults to every day at 03:00 UTC. */
14
+ cron?: string;
15
+ /** Revision-history retention. `keepLast` is evaluated per record. */
16
+ history?: HistoryRetentionTarget;
17
+ /** Action-log retention. `keepLast` is evaluated globally. */
18
+ auditLog?: AuditLogRetentionTarget;
19
+ /** BullMQ options for each scheduled maintenance job. */
20
+ jobOptions?: Omit<JobsOptions, 'repeat'>;
21
+ }
22
+ export interface RetentionRunResult {
23
+ history?: number;
24
+ auditLog?: number;
25
+ }
26
+ //# sourceMappingURL=retention.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.types.d.ts","sourceRoot":"","sources":["../../src/retention/retention.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAEzC,MAAM,WAAW,aAAa,CAAC,UAAU;IACvC,KAAK,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CAC9C;AAED,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,KAAK,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAA;CACvC;AAED,MAAM,WAAW,uBAAwB,SAAQ,kBAAkB;IACjE,KAAK,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAA;CACzC;AAED,MAAM,WAAW,sBAAsB;IACrC,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sEAAsE;IACtE,OAAO,CAAC,EAAE,sBAAsB,CAAA;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,uBAAuB,CAAA;IAClC,yDAAyD;IACzD,UAAU,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;CACzC;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=retention.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.types.js","sourceRoot":"","sources":["../../src/retention/retention.types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modern-admin/queue",
3
- "version": "0.6.0",
3
+ "version": "0.9.0",
4
4
  "description": "BullMQ-based queue + cron module for Modern Admin (NestJS).",
5
5
  "homepage": "https://github.com/modern-admin/modern-admin/tree/main/packages/queue#readme",
6
6
  "keywords": [
@@ -44,6 +44,9 @@
44
44
  }
45
45
  }
46
46
  },
47
+ "dependencies": {
48
+ "@modern-admin/core": "^0.9.0"
49
+ },
47
50
  "devDependencies": {
48
51
  "@modern-admin/tsconfig": "0.4.0",
49
52
  "@nestjs/bullmq": "^11.0.5",
@@ -1,4 +1,4 @@
1
- export const CRON_QUEUE = 'ma:cron'
1
+ export const CRON_QUEUE = 'ma-cron'
2
2
  export const DEFAULT_CRON_WORKER_CONCURRENCY = 4
3
3
  export const CRON_LOCK_PREFIX = 'ma:cron-lock:'
4
4
  export const DEFAULT_CRON_LOCK_TTL = 300
@@ -7,7 +7,7 @@ import {
7
7
  DEFAULT_CRON_LOCK_TTL,
8
8
  DEFAULT_CRON_WORKER_CONCURRENCY,
9
9
  } from './cron.constants.js'
10
- import type { CronService } from './cron.service.js'
10
+ import { CronService } from './cron.service.js'
11
11
 
12
12
  @Processor(CRON_QUEUE, { concurrency: DEFAULT_CRON_WORKER_CONCURRENCY })
13
13
  export class CronProcessor extends WorkerHost {
package/src/index.ts CHANGED
@@ -17,3 +17,16 @@ export {
17
17
  type CronHandler,
18
18
  type CronTaskDefinition,
19
19
  } from './cron'
20
+
21
+ export {
22
+ RetentionModule,
23
+ RetentionService,
24
+ RETENTION_OPTIONS,
25
+ DEFAULT_RETENTION_CRON,
26
+ SYSTEM_RETENTION_TASK,
27
+ type AuditLogRetentionTarget,
28
+ type HistoryRetentionTarget,
29
+ type PrunableStore,
30
+ type RetentionModuleOptions,
31
+ type RetentionRunResult,
32
+ } from './retention'
@@ -2,6 +2,10 @@ import { type DynamicModule, Module } from '@nestjs/common'
2
2
  import { BullModule } from '@nestjs/bullmq'
3
3
  import type { QueueModuleOptions, QueueRootOptions } from './queue.types.js'
4
4
 
5
+ export const normalizeQueueConnection = (
6
+ connection: QueueRootOptions['connection'],
7
+ ): object => typeof connection === 'string' ? { url: connection } : connection
8
+
5
9
  /**
6
10
  * BullMQ integration module for modern-admin NestJS applications.
7
11
  *
@@ -30,7 +34,7 @@ export class QueueModule {
30
34
  global: true,
31
35
  imports: [
32
36
  BullModule.forRoot({
33
- connection: options.connection as object,
37
+ connection: normalizeQueueConnection(options.connection),
34
38
  defaultJobOptions: options.defaultJobOptions,
35
39
  }),
36
40
  ],
@@ -65,7 +69,7 @@ export class QueueModule {
65
69
  useFactory: async (...args: unknown[]) => {
66
70
  const resolved = await opts.useFactory(...args)
67
71
  return {
68
- connection: resolved.connection as object,
72
+ connection: normalizeQueueConnection(resolved.connection),
69
73
  defaultJobOptions: resolved.defaultJobOptions,
70
74
  }
71
75
  },
@@ -0,0 +1,11 @@
1
+ export { RetentionModule } from './retention.module.js'
2
+ export { RetentionService } from './retention.service.js'
3
+ export { RETENTION_OPTIONS } from './retention.tokens.js'
4
+ export { DEFAULT_RETENTION_CRON, SYSTEM_RETENTION_TASK } from './retention.constants.js'
5
+ export type {
6
+ AuditLogRetentionTarget,
7
+ HistoryRetentionTarget,
8
+ PrunableStore,
9
+ RetentionModuleOptions,
10
+ RetentionRunResult,
11
+ } from './retention.types.js'
@@ -0,0 +1,2 @@
1
+ export const SYSTEM_RETENTION_TASK = 'ma:system-retention'
2
+ export const DEFAULT_RETENTION_CRON = '0 3 * * *'
@@ -0,0 +1,42 @@
1
+ import { type DynamicModule, Module } from '@nestjs/common'
2
+ import { CronModule } from '../cron/cron.module.js'
3
+ import { RetentionService } from './retention.service.js'
4
+ import { RETENTION_OPTIONS } from './retention.tokens.js'
5
+ import type { RetentionModuleOptions } from './retention.types.js'
6
+
7
+ const assertBound = (name: string, value: number | undefined): void => {
8
+ if (value === undefined) return
9
+ if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {
10
+ throw new Error(`${name} must be a non-negative integer`)
11
+ }
12
+ }
13
+
14
+ const validateOptions = (options: RetentionModuleOptions): void => {
15
+ if (options.cron !== undefined && options.cron.trim().length === 0) {
16
+ throw new Error('retention cron must not be empty')
17
+ }
18
+ assertBound('history.keepLast', options.history?.keepLast)
19
+ assertBound('history.keepDays', options.history?.keepDays)
20
+ assertBound('auditLog.keepLast', options.auditLog?.keepLast)
21
+ assertBound('auditLog.keepDays', options.auditLog?.keepDays)
22
+ }
23
+
24
+ /**
25
+ * Schedules history and action-log pruning as a durable BullMQ cron task.
26
+ * Requires `QueueModule.forRoot()` in the host application's root module.
27
+ */
28
+ @Module({})
29
+ export class RetentionModule {
30
+ static forRoot(options: RetentionModuleOptions): DynamicModule {
31
+ validateOptions(options)
32
+ return {
33
+ module: RetentionModule,
34
+ imports: [CronModule],
35
+ providers: [
36
+ { provide: RETENTION_OPTIONS, useValue: options },
37
+ RetentionService,
38
+ ],
39
+ exports: [RetentionService],
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,91 @@
1
+ import { Inject, Injectable, type OnModuleInit } from '@nestjs/common'
2
+ import type { ActionLogRetention, HistoryRetention } from '@modern-admin/core'
3
+ import { CronService } from '../cron/cron.service.js'
4
+ import { DEFAULT_RETENTION_CRON, SYSTEM_RETENTION_TASK } from './retention.constants.js'
5
+ import { RETENTION_OPTIONS } from './retention.tokens.js'
6
+ import type {
7
+ AuditLogRetentionTarget,
8
+ HistoryRetentionTarget,
9
+ RetentionModuleOptions,
10
+ RetentionRunResult,
11
+ } from './retention.types.js'
12
+
13
+ const hasBounds = (retention: { keepLast?: number; keepDays?: number }): boolean =>
14
+ retention.keepLast !== undefined || retention.keepDays !== undefined
15
+
16
+ @Injectable()
17
+ export class RetentionService implements OnModuleInit {
18
+ constructor(
19
+ @Inject(RETENTION_OPTIONS) private readonly options: RetentionModuleOptions,
20
+ private readonly cron: CronService,
21
+ ) {}
22
+
23
+ onModuleInit(): void {
24
+ if (!this.hasWork()) return
25
+
26
+ this.cron.register({
27
+ name: SYSTEM_RETENTION_TASK,
28
+ cron: this.options.cron ?? DEFAULT_RETENTION_CRON,
29
+ skipIfRunning: true,
30
+ opts: {
31
+ attempts: 3,
32
+ backoff: { type: 'exponential', delay: 1_000 },
33
+ ...this.options.jobOptions,
34
+ },
35
+ handler: () => this.run(),
36
+ })
37
+ }
38
+
39
+ /** Execute every configured retention target. Called by the BullMQ worker. */
40
+ async run(): Promise<RetentionRunResult> {
41
+ const result: RetentionRunResult = {}
42
+ const failures: unknown[] = []
43
+
44
+ if (this.options.history && hasBounds(this.options.history)) {
45
+ try {
46
+ result.history = await this.pruneHistory(this.options.history)
47
+ } catch (err: unknown) {
48
+ failures.push(err)
49
+ }
50
+ }
51
+ if (this.options.auditLog && hasBounds(this.options.auditLog)) {
52
+ try {
53
+ result.auditLog = await this.pruneAuditLog(this.options.auditLog)
54
+ } catch (err: unknown) {
55
+ failures.push(err)
56
+ }
57
+ }
58
+
59
+ if (failures.length === 1) {
60
+ throw failures[0]
61
+ }
62
+ if (failures.length > 1) {
63
+ throw new AggregateError(failures, 'Multiple retention targets failed')
64
+ }
65
+
66
+ return result
67
+ }
68
+
69
+ private hasWork(): boolean {
70
+ return Boolean(
71
+ (this.options.history && hasBounds(this.options.history))
72
+ || (this.options.auditLog && hasBounds(this.options.auditLog)),
73
+ )
74
+ }
75
+
76
+ private pruneHistory(target: HistoryRetentionTarget): Promise<number> {
77
+ const retention: HistoryRetention = {
78
+ ...(target.keepLast !== undefined ? { keepLast: target.keepLast } : {}),
79
+ ...(target.keepDays !== undefined ? { keepDays: target.keepDays } : {}),
80
+ }
81
+ return target.store.prune(retention)
82
+ }
83
+
84
+ private pruneAuditLog(target: AuditLogRetentionTarget): Promise<number> {
85
+ const retention: ActionLogRetention = {
86
+ ...(target.keepLast !== undefined ? { keepLast: target.keepLast } : {}),
87
+ ...(target.keepDays !== undefined ? { keepDays: target.keepDays } : {}),
88
+ }
89
+ return target.store.prune(retention)
90
+ }
91
+ }
@@ -0,0 +1 @@
1
+ export const RETENTION_OPTIONS = Symbol.for('@modern-admin/queue:RetentionOptions')
@@ -0,0 +1,30 @@
1
+ import type { ActionLogRetention, HistoryRetention } from '@modern-admin/core'
2
+ import type { JobsOptions } from 'bullmq'
3
+
4
+ export interface PrunableStore<TRetention> {
5
+ prune(retention: TRetention): Promise<number>
6
+ }
7
+
8
+ export interface HistoryRetentionTarget extends HistoryRetention {
9
+ store: PrunableStore<HistoryRetention>
10
+ }
11
+
12
+ export interface AuditLogRetentionTarget extends ActionLogRetention {
13
+ store: PrunableStore<ActionLogRetention>
14
+ }
15
+
16
+ export interface RetentionModuleOptions {
17
+ /** BullMQ cron expression. Defaults to every day at 03:00 UTC. */
18
+ cron?: string
19
+ /** Revision-history retention. `keepLast` is evaluated per record. */
20
+ history?: HistoryRetentionTarget
21
+ /** Action-log retention. `keepLast` is evaluated globally. */
22
+ auditLog?: AuditLogRetentionTarget
23
+ /** BullMQ options for each scheduled maintenance job. */
24
+ jobOptions?: Omit<JobsOptions, 'repeat'>
25
+ }
26
+
27
+ export interface RetentionRunResult {
28
+ history?: number
29
+ auditLog?: number
30
+ }