@spinajs/queue 2.0.481 → 2.0.482
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/config/queue.d.ts +10 -0
- package/lib/cjs/config/queue.d.ts.map +1 -1
- package/lib/cjs/config/queue.js +21 -0
- package/lib/cjs/config/queue.js.map +1 -1
- package/lib/cjs/decorators.d.ts.map +1 -1
- package/lib/cjs/decorators.js.map +1 -1
- package/lib/cjs/fp.d.ts.map +1 -1
- package/lib/cjs/fp.js.map +1 -1
- package/lib/cjs/index.d.ts +13 -2
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +103 -14
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/interfaces.d.ts +178 -7
- package/lib/cjs/interfaces.d.ts.map +1 -1
- package/lib/cjs/interfaces.js +59 -11
- package/lib/cjs/interfaces.js.map +1 -1
- package/lib/cjs/migrations/Queue_2026_06_30_00_00_00.d.ts +10 -0
- package/lib/cjs/migrations/Queue_2026_06_30_00_00_00.d.ts.map +1 -0
- package/lib/cjs/migrations/Queue_2026_06_30_00_00_00.js +29 -0
- package/lib/cjs/migrations/Queue_2026_06_30_00_00_00.js.map +1 -0
- package/lib/cjs/migrations/Queue_2026_07_02_00_00_00.d.ts +14 -0
- package/lib/cjs/migrations/Queue_2026_07_02_00_00_00.d.ts.map +1 -0
- package/lib/cjs/migrations/Queue_2026_07_02_00_00_00.js +53 -0
- package/lib/cjs/migrations/Queue_2026_07_02_00_00_00.js.map +1 -0
- package/lib/cjs/migrations/Queue_2026_07_10_00_00_00.d.ts +10 -0
- package/lib/cjs/migrations/Queue_2026_07_10_00_00_00.d.ts.map +1 -0
- package/lib/cjs/migrations/Queue_2026_07_10_00_00_00.js +31 -0
- package/lib/cjs/migrations/Queue_2026_07_10_00_00_00.js.map +1 -0
- package/lib/cjs/migrations/Queue_2026_07_17_00_00_00.d.ts +16 -0
- package/lib/cjs/migrations/Queue_2026_07_17_00_00_00.d.ts.map +1 -0
- package/lib/cjs/migrations/Queue_2026_07_17_00_00_00.js +49 -0
- package/lib/cjs/migrations/Queue_2026_07_17_00_00_00.js.map +1 -0
- package/lib/cjs/models/JobModel.d.ts +66 -4
- package/lib/cjs/models/JobModel.d.ts.map +1 -1
- package/lib/cjs/models/JobModel.js +43 -2
- package/lib/cjs/models/JobModel.js.map +1 -1
- package/lib/cjs/services/JobRetentionService.d.ts +26 -0
- package/lib/cjs/services/JobRetentionService.d.ts.map +1 -0
- package/lib/cjs/services/JobRetentionService.js +87 -0
- package/lib/cjs/services/JobRetentionService.js.map +1 -0
- package/lib/mjs/config/queue.d.ts +10 -0
- package/lib/mjs/config/queue.d.ts.map +1 -1
- package/lib/mjs/config/queue.js +21 -0
- package/lib/mjs/config/queue.js.map +1 -1
- package/lib/mjs/decorators.d.ts.map +1 -1
- package/lib/mjs/decorators.js.map +1 -1
- package/lib/mjs/fp.d.ts.map +1 -1
- package/lib/mjs/fp.js.map +1 -1
- package/lib/mjs/index.d.ts +13 -2
- package/lib/mjs/index.d.ts.map +1 -1
- package/lib/mjs/index.js +105 -16
- package/lib/mjs/index.js.map +1 -1
- package/lib/mjs/interfaces.d.ts +178 -7
- package/lib/mjs/interfaces.d.ts.map +1 -1
- package/lib/mjs/interfaces.js +57 -10
- package/lib/mjs/interfaces.js.map +1 -1
- package/lib/mjs/migrations/Queue_2026_06_30_00_00_00.d.ts +10 -0
- package/lib/mjs/migrations/Queue_2026_06_30_00_00_00.d.ts.map +1 -0
- package/lib/mjs/migrations/Queue_2026_06_30_00_00_00.js +26 -0
- package/lib/mjs/migrations/Queue_2026_06_30_00_00_00.js.map +1 -0
- package/lib/mjs/migrations/Queue_2026_07_02_00_00_00.d.ts +14 -0
- package/lib/mjs/migrations/Queue_2026_07_02_00_00_00.d.ts.map +1 -0
- package/lib/mjs/migrations/Queue_2026_07_02_00_00_00.js +50 -0
- package/lib/mjs/migrations/Queue_2026_07_02_00_00_00.js.map +1 -0
- package/lib/mjs/migrations/Queue_2026_07_10_00_00_00.d.ts +10 -0
- package/lib/mjs/migrations/Queue_2026_07_10_00_00_00.d.ts.map +1 -0
- package/lib/mjs/migrations/Queue_2026_07_10_00_00_00.js +28 -0
- package/lib/mjs/migrations/Queue_2026_07_10_00_00_00.js.map +1 -0
- package/lib/mjs/migrations/Queue_2026_07_17_00_00_00.d.ts +16 -0
- package/lib/mjs/migrations/Queue_2026_07_17_00_00_00.d.ts.map +1 -0
- package/lib/mjs/migrations/Queue_2026_07_17_00_00_00.js +46 -0
- package/lib/mjs/migrations/Queue_2026_07_17_00_00_00.js.map +1 -0
- package/lib/mjs/models/JobModel.d.ts +66 -4
- package/lib/mjs/models/JobModel.d.ts.map +1 -1
- package/lib/mjs/models/JobModel.js +42 -2
- package/lib/mjs/models/JobModel.js.map +1 -1
- package/lib/mjs/services/JobRetentionService.d.ts +26 -0
- package/lib/mjs/services/JobRetentionService.d.ts.map +1 -0
- package/lib/mjs/services/JobRetentionService.js +84 -0
- package/lib/mjs/services/JobRetentionService.js.map +1 -0
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +9 -6
|
@@ -0,0 +1,87 @@
|
|
|
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.DefaultJobRetentionService = void 0;
|
|
13
|
+
const di_1 = require("@spinajs/di");
|
|
14
|
+
const log_1 = require("@spinajs/log");
|
|
15
|
+
const luxon_1 = require("luxon");
|
|
16
|
+
const interfaces_js_1 = require("../interfaces.js");
|
|
17
|
+
const JobModel_js_1 = require("../models/JobModel.js");
|
|
18
|
+
/**
|
|
19
|
+
* How often ( ms ) to run the purge when `queue.retention.interval` is not set.
|
|
20
|
+
*/
|
|
21
|
+
const DEFAULT_INTERVAL_MS = 60 * 60 * 1000;
|
|
22
|
+
/**
|
|
23
|
+
* Built-in {@link JobRetentionService}. Periodically deletes terminal jobs older than the
|
|
24
|
+
* configured `maxAge` so the `queue_jobs` table doesn't grow unbounded. All timings / statuses
|
|
25
|
+
* come from the injected `queue.retention` config block - nothing is hardcoded except the
|
|
26
|
+
* fallback interval used when none is configured.
|
|
27
|
+
*/
|
|
28
|
+
let DefaultJobRetentionService = class DefaultJobRetentionService extends interfaces_js_1.JobRetentionService {
|
|
29
|
+
async resolve() {
|
|
30
|
+
this.startRetention();
|
|
31
|
+
}
|
|
32
|
+
async dispose() {
|
|
33
|
+
if (this.RetentionTimer) {
|
|
34
|
+
clearInterval(this.RetentionTimer);
|
|
35
|
+
this.RetentionTimer = undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Starts the periodic job-retention purge when configured. No-op if retention is disabled
|
|
40
|
+
* or no `maxAge` is set.
|
|
41
|
+
*/
|
|
42
|
+
startRetention() {
|
|
43
|
+
if (!this.Options?.enabled || !this.Options.maxAge) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const interval = this.Options.interval ?? DEFAULT_INTERVAL_MS;
|
|
47
|
+
const maxAge = this.Options.maxAge;
|
|
48
|
+
this.RetentionTimer = setInterval(() => {
|
|
49
|
+
const cutoff = luxon_1.DateTime.now().minus({ milliseconds: maxAge });
|
|
50
|
+
this.purgeJobs(cutoff, this.Options.statuses)
|
|
51
|
+
.then((n) => {
|
|
52
|
+
if (n > 0) {
|
|
53
|
+
this.Log.info(`Retention purge removed ${n} job(s) older than ${cutoff.toISO()}`);
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
.catch((err) => this.Log.error(err, 'Job retention purge failed'));
|
|
57
|
+
}, interval);
|
|
58
|
+
// don't keep the process alive just for the purge timer
|
|
59
|
+
this.RetentionTimer.unref?.();
|
|
60
|
+
this.Log.info(`Job retention enabled: purging jobs older than ${maxAge}ms every ${interval}ms`);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Deletes terminal ( or given ) jobs created before `olderThan`. The set is selected with the
|
|
64
|
+
* JobModel query scopes ( status + date ), then removed by id.
|
|
65
|
+
*/
|
|
66
|
+
async purgeJobs(olderThan, statuses) {
|
|
67
|
+
const rows = await JobModel_js_1.JobModel.query()
|
|
68
|
+
.columns(['Id'])
|
|
69
|
+
.withStatus(statuses ?? JobModel_js_1.JOB_TERMINAL_STATUSES)
|
|
70
|
+
.olderThan(olderThan);
|
|
71
|
+
const ids = rows.map((r) => r.Id);
|
|
72
|
+
if (ids.length === 0) {
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
await JobModel_js_1.JobModel.destroy(ids);
|
|
76
|
+
return ids.length;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
exports.DefaultJobRetentionService = DefaultJobRetentionService;
|
|
80
|
+
__decorate([
|
|
81
|
+
(0, log_1.Logger)('queue'),
|
|
82
|
+
__metadata("design:type", log_1.Log)
|
|
83
|
+
], DefaultJobRetentionService.prototype, "Log", void 0);
|
|
84
|
+
exports.DefaultJobRetentionService = DefaultJobRetentionService = __decorate([
|
|
85
|
+
(0, di_1.Injectable)(interfaces_js_1.JobRetentionService)
|
|
86
|
+
], DefaultJobRetentionService);
|
|
87
|
+
//# sourceMappingURL=JobRetentionService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JobRetentionService.js","sourceRoot":"","sources":["../../../src/services/JobRetentionService.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oCAAyC;AACzC,sCAA2C;AAC3C,iCAAiC;AACjC,oDAAuD;AACvD,uDAAmF;AAEnF;;GAEG;AACH,MAAM,mBAAmB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAE3C;;;;;GAKG;AAEI,IAAM,0BAA0B,GAAhC,MAAM,0BAA2B,SAAQ,mCAAmB;IAM1D,KAAK,CAAC,OAAO;QAClB,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAEM,KAAK,CAAC,OAAO;QAClB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACnC,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAClC,CAAC;IACH,CAAC;IAED;;;OAGG;IACO,cAAc;QACtB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACnD,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,mBAAmB,CAAC;QAC9D,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QAEnC,IAAI,CAAC,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE;YACrC,MAAM,MAAM,GAAG,gBAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;YAC9D,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;iBAC1C,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;gBACV,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACV,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,2BAA2B,CAAC,sBAAsB,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACpF,CAAC;YACH,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,4BAA4B,CAAC,CAAC,CAAC;QACvE,CAAC,EAAE,QAAQ,CAAC,CAAC;QAEb,wDAAwD;QACvD,IAAI,CAAC,cAAyC,CAAC,KAAK,EAAE,EAAE,CAAC;QAE1D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,kDAAkD,MAAM,YAAY,QAAQ,IAAI,CAAC,CAAC;IAClG,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,SAAS,CAAC,SAAmB,EAAE,QAAmB;QAC7D,MAAM,IAAI,GAAG,MAAM,sBAAQ,CAAC,KAAK,EAAE;aAChC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;aACf,UAAU,CAAE,QAAwB,IAAI,mCAAqB,CAAC;aAC9D,SAAS,CAAC,SAAS,CAAC,CAAC;QAExB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,sBAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,GAAG,CAAC,MAAM,CAAC;IACpB,CAAC;CACF,CAAA;AAhEY,gEAA0B;AAE3B;IADT,IAAA,YAAM,EAAC,OAAO,CAAC;8BACD,SAAG;uDAAC;qCAFR,0BAA0B;IADtC,IAAA,eAAU,EAAC,mCAAmB,CAAC;GACnB,0BAA0B,CAgEtC"}
|
|
@@ -5,6 +5,16 @@ declare const queue: {
|
|
|
5
5
|
name: string;
|
|
6
6
|
service: string;
|
|
7
7
|
}[];
|
|
8
|
+
deduplicate: boolean;
|
|
9
|
+
retention: {
|
|
10
|
+
service: string;
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
interval: number;
|
|
13
|
+
};
|
|
14
|
+
progress: {
|
|
15
|
+
minDelta: number;
|
|
16
|
+
minInterval: number;
|
|
17
|
+
};
|
|
8
18
|
};
|
|
9
19
|
};
|
|
10
20
|
export default queue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../../src/config/queue.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,KAAK
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../../src/config/queue.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,KAAK;;;;;;;;;;;;;;;;;;CAqCV,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
package/lib/mjs/config/queue.js
CHANGED
|
@@ -10,6 +10,27 @@ const queue = {
|
|
|
10
10
|
service: 'BlackHoleQueueClient',
|
|
11
11
|
},
|
|
12
12
|
],
|
|
13
|
+
// Skip re-executing a job whose tracking row ( queue_jobs ) is already terminal
|
|
14
|
+
// ( success / error / dead ). Messaging is at-least-once, so duplicates happen on
|
|
15
|
+
// consumer crash and broker failover - dedup keeps jobs idempotent. Defaults to true.
|
|
16
|
+
deduplicate: true,
|
|
17
|
+
// Periodic cleanup of tracked jobs ( queue_jobs rows ). The `service` selects the
|
|
18
|
+
// JobRetentionService implementation; swap it to plug in a custom purge strategy.
|
|
19
|
+
// Disabled by default - set `enabled: true` and a `maxAge` ( ms ) to opt in.
|
|
20
|
+
retention: {
|
|
21
|
+
service: 'DefaultJobRetentionService',
|
|
22
|
+
enabled: false,
|
|
23
|
+
interval: 60 * 60 * 1000, // how often ( ms ) to run the purge
|
|
24
|
+
// maxAge: 7 * 24 * 60 * 60 * 1000, // delete terminal jobs older than this ( ms )
|
|
25
|
+
// statuses: ['success', 'error', 'dead'], // which statuses to purge
|
|
26
|
+
},
|
|
27
|
+
// Throttle job progress persistence so a chatty job doesn't write to the DB on every
|
|
28
|
+
// callback. A non-final, meta-less progress update is skipped unless it moved at least
|
|
29
|
+
// `minDelta` % or `minInterval` ms have passed since the last persisted write.
|
|
30
|
+
progress: {
|
|
31
|
+
minDelta: 5, // minimum progress delta ( % ) between throttled writes
|
|
32
|
+
minInterval: 1000, // minimum time ( ms ) between throttled writes
|
|
33
|
+
},
|
|
13
34
|
},
|
|
14
35
|
};
|
|
15
36
|
export default queue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../../src/config/queue.ts"],"names":[],"mappings":"AAAA,MAAM,KAAK,GAAG;IACZ,KAAK,EAAE;QACL,kDAAkD;QAClD,gEAAgE;QAChE,sEAAsE;QACtE,OAAO,EAAE,YAAY;QACrB,WAAW,EAAE;YACX;gBACE,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,sBAAsB;aAChC;SACF;KACF;CACF,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../../src/config/queue.ts"],"names":[],"mappings":"AAAA,MAAM,KAAK,GAAG;IACZ,KAAK,EAAE;QACL,kDAAkD;QAClD,gEAAgE;QAChE,sEAAsE;QACtE,OAAO,EAAE,YAAY;QACrB,WAAW,EAAE;YACX;gBACE,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,sBAAsB;aAChC;SACF;QAED,gFAAgF;QAChF,kFAAkF;QAClF,sFAAsF;QACtF,WAAW,EAAE,IAAI;QAEjB,kFAAkF;QAClF,kFAAkF;QAClF,6EAA6E;QAC7E,SAAS,EAAE;YACT,OAAO,EAAE,4BAA4B;YACrC,OAAO,EAAE,KAAK;YACd,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,oCAAoC;YAC9D,kFAAkF;YAClF,qEAAqE;SACtE;QAED,qFAAqF;QACrF,uFAAuF;QACvF,+EAA+E;QAC/E,QAAQ,EAAE;YACR,QAAQ,EAAE,CAAC,EAAE,wDAAwD;YACrE,WAAW,EAAE,IAAI,EAAE,+CAA+C;SACnE;KACF;CACF,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,GAAG,KACT,QAAQ,GAAG,UAWpB;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,IAClC,QAAQ,GAAG,UAYpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,MAAM,UAAU,GAAG;IACjB,OAAO,CAAC,MAAW,EAAE,EAAE;QACrB,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,eAAe,EAAE,MAAM,CAAC,EAAE,CAAC;YAClD,OAAO,CAAC,cAAc,CACpB,eAAe,EACf;gBACE,IAAI,EAAE,KAAK;aACZ,EACD,MAAM,CACP,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,OAAsB;IAC1C,OAAO,CAAC,MAAW,EAAE,EAAE;QACrB,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,eAAe,EAAE,MAAM,CAAC,EAAE,CAAC;YAClD,OAAO,CAAC,cAAc,CACpB,eAAe,EACf;gBACE,GAAG,OAAO;gBACV,IAAI,EAAE,OAAO;aACd,EACD,MAAM,CACP,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
package/lib/mjs/fp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fp.d.ts","sourceRoot":"","sources":["../../src/fp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAgB,MAAM,iBAAiB,CAAC;AAIpF,wBAAgB,GAAG,CAAC,KAAK,EAAE,aAAa,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"fp.d.ts","sourceRoot":"","sources":["../../src/fp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAgB,MAAM,iBAAiB,CAAC;AAIpF,wBAAgB,GAAG,CAAC,KAAK,EAAE,aAAa,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAErF"}
|
package/lib/mjs/fp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fp.js","sourceRoot":"","sources":["../../src/fp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,MAAM,UAAU,GAAG,CAAC,KAA4C;IAC9D,OAAO,GAAG,EAAE,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"fp.js","sourceRoot":"","sources":["../../src/fp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,MAAM,UAAU,GAAG,CAAC,KAA4C;IAC9D,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,OAAqB,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9F,CAAC"}
|
package/lib/mjs/index.d.ts
CHANGED
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
import { Constructor } from '@spinajs/di';
|
|
2
2
|
import { Log } from '@spinajs/log';
|
|
3
|
-
import { QueueClient, QueueJob, QueueEvent, IQueueMessage, QueueMessage, QueueService } from './interfaces.js';
|
|
3
|
+
import { QueueClient, QueueJob, QueueEvent, IQueueMessage, QueueMessage, QueueService, JobRetentionService } from './interfaces.js';
|
|
4
4
|
export * from './BlackHoleQueueClient.js';
|
|
5
5
|
export * from './interfaces.js';
|
|
6
6
|
export * from './decorators.js';
|
|
7
7
|
export * from './models/JobModel.js';
|
|
8
|
+
export * from './services/JobRetentionService.js';
|
|
8
9
|
export * from './migrations/Queue_2022_10_18_01_13_00.js';
|
|
10
|
+
export * from './migrations/Queue_2026_06_30_00_00_00.js';
|
|
11
|
+
export * from './migrations/Queue_2026_07_02_00_00_00.js';
|
|
12
|
+
export * from './migrations/Queue_2026_07_10_00_00_00.js';
|
|
13
|
+
export * from './migrations/Queue_2026_07_17_00_00_00.js';
|
|
9
14
|
export * from './fp.js';
|
|
10
15
|
export declare class DefaultQueueService extends QueueService {
|
|
11
16
|
protected Log: Log;
|
|
12
17
|
protected Connections: Map<string, QueueClient>;
|
|
18
|
+
/**
|
|
19
|
+
* Config-selected retention service that periodically purges old tracked jobs.
|
|
20
|
+
* Started / stopped by DI on injection / disposal. May be undefined if retention
|
|
21
|
+
* is not configured.
|
|
22
|
+
*/
|
|
23
|
+
protected Retention?: JobRetentionService;
|
|
13
24
|
dispose(): Promise<void>;
|
|
14
|
-
emit(event: IQueueMessage | QueueEvent | QueueJob): Promise<
|
|
25
|
+
emit(event: IQueueMessage | QueueEvent | QueueJob): Promise<string | undefined>;
|
|
15
26
|
stopConsuming(event: Constructor<QueueMessage>): Promise<void>;
|
|
16
27
|
/**
|
|
17
28
|
*
|
package/lib/mjs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAmC,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAmC,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAoB,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAS,MAAM,iBAAiB,CAAC;AAM7J,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,SAAS,CAAC;AAMxB,qBACa,mBAAoB,SAAQ,YAAY;IAEnD,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAGnB,SAAS,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAEhD;;;;OAIG;IAEH,SAAS,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAE7B,OAAO;IAoBP,IAAI,CAAC,KAAK,EAAE,aAAa,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAwB/E,aAAa,CAAC,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC;IAI3D;;;;;;;;;;;;;;;OAeG;IACU,OAAO,CAAC,CAAC,SAAS,YAAY,EAAE,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO;IAwKnK;;;;OAIG;IACI,GAAG,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW;CAG7C"}
|
package/lib/mjs/index.js
CHANGED
|
@@ -10,8 +10,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
import { UnexpectedServerError, InvalidArgument, ConnectionNotFound } from '@spinajs/exceptions';
|
|
11
11
|
import { DI, Injectable, ServiceNotFound } from '@spinajs/di';
|
|
12
12
|
import { Log, Logger } from '@spinajs/log';
|
|
13
|
-
import { QueueClient, QueueJob, QueueEvent, QueueService, isJob } from './interfaces.js';
|
|
14
|
-
import { JobModel } from './models/JobModel.js';
|
|
13
|
+
import { QueueClient, QueueJob, QueueEvent, QueueService, JobRetentionService, isJob } from './interfaces.js';
|
|
14
|
+
import { JobModel, JOB_TERMINAL_STATUSES } from './models/JobModel.js';
|
|
15
15
|
import { v4 as uuidv4 } from 'uuid';
|
|
16
16
|
import { AutoinjectService } from '@spinajs/configuration';
|
|
17
17
|
import { DateTime } from 'luxon';
|
|
@@ -19,10 +19,26 @@ export * from './BlackHoleQueueClient.js';
|
|
|
19
19
|
export * from './interfaces.js';
|
|
20
20
|
export * from './decorators.js';
|
|
21
21
|
export * from './models/JobModel.js';
|
|
22
|
+
export * from './services/JobRetentionService.js';
|
|
22
23
|
export * from './migrations/Queue_2022_10_18_01_13_00.js';
|
|
24
|
+
export * from './migrations/Queue_2026_06_30_00_00_00.js';
|
|
25
|
+
export * from './migrations/Queue_2026_07_02_00_00_00.js';
|
|
26
|
+
export * from './migrations/Queue_2026_07_10_00_00_00.js';
|
|
27
|
+
export * from './migrations/Queue_2026_07_17_00_00_00.js';
|
|
23
28
|
export * from './fp.js';
|
|
29
|
+
/** Fallback progress-throttle values used when `queue.progress` is not configured. */
|
|
30
|
+
const DEFAULT_PROGRESS_MIN_DELTA = 5;
|
|
31
|
+
const DEFAULT_PROGRESS_MIN_INTERVAL_MS = 1000;
|
|
24
32
|
let DefaultQueueService = class DefaultQueueService extends QueueService {
|
|
25
33
|
async dispose() {
|
|
34
|
+
if (this.Retention) {
|
|
35
|
+
try {
|
|
36
|
+
await this.Retention.dispose();
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
this.Log.error(err, 'Cannot dispose job retention service');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
26
42
|
this.Connections.forEach(async (val) => {
|
|
27
43
|
try {
|
|
28
44
|
await val.dispose();
|
|
@@ -35,24 +51,21 @@ let DefaultQueueService = class DefaultQueueService extends QueueService {
|
|
|
35
51
|
}
|
|
36
52
|
async emit(event) {
|
|
37
53
|
const connections = this.getConnectionsForMessage(event);
|
|
54
|
+
let jobId;
|
|
38
55
|
for (let c of connections) {
|
|
39
56
|
const connection = this.Connections.get(c);
|
|
40
57
|
if (!connection) {
|
|
41
58
|
throw new ConnectionNotFound(`Queue connection ${c} not found. Please check your configuration before emitting events to this connection.`);
|
|
42
59
|
}
|
|
43
60
|
if (isJob(event)) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
jModel.Name = event.Name;
|
|
47
|
-
jModel.Status = 'created';
|
|
48
|
-
jModel.Progress = 0;
|
|
49
|
-
jModel.Connection = c;
|
|
50
|
-
await jModel.insert();
|
|
51
|
-
event.JobId = jModel.JobId;
|
|
61
|
+
event.JobId = event.JobId ?? uuidv4(); // generate only; consumer writes the row
|
|
62
|
+
jobId = event.JobId;
|
|
52
63
|
}
|
|
53
64
|
await connection.emit(event);
|
|
54
65
|
this.Log.trace(`Emitted message ${event.Name}, type: ${event.Type} to connection ${c}`);
|
|
55
66
|
}
|
|
67
|
+
// for jobs this is the id the caller uses to track progress / status
|
|
68
|
+
return jobId;
|
|
56
69
|
}
|
|
57
70
|
async stopConsuming(event) {
|
|
58
71
|
this.getConnectionsForMessage(event).forEach((c) => this.Connections.get(c).unsubscribe(event));
|
|
@@ -99,9 +112,46 @@ let DefaultQueueService = class DefaultQueueService extends QueueService {
|
|
|
99
112
|
*/
|
|
100
113
|
if (ev instanceof QueueJob) {
|
|
101
114
|
let jobResult = null;
|
|
102
|
-
|
|
115
|
+
// Consumer owns the tracking row. First receipt inserts; a redelivery finds the
|
|
116
|
+
// row from the prior attempt. The queue_jobs.JobId unique index makes a rare
|
|
117
|
+
// concurrent double-receipt safe (second insert collides -> re-read).
|
|
118
|
+
let jModel = await JobModel.where({ JobId: ev.JobId }).first();
|
|
119
|
+
if (!jModel) {
|
|
120
|
+
jModel = new JobModel();
|
|
121
|
+
jModel.JobId = ev.JobId;
|
|
122
|
+
jModel.Name = ev.Name;
|
|
123
|
+
jModel.Connection = c;
|
|
124
|
+
jModel.Attempt = 0;
|
|
125
|
+
jModel.Progress = 0;
|
|
126
|
+
// set Status explicitly so tracking never depends on the DB column default,
|
|
127
|
+
// which can differ across dialects ( and MySQL MODIFY COLUMN can drop it ).
|
|
128
|
+
jModel.Status = 'created';
|
|
129
|
+
// capture the dispatch-time attempt ceiling ( retries + 1 ) so it stays authoritative
|
|
130
|
+
// across redeliveries and consumers can render Attempt/MaxAttempts consistently.
|
|
131
|
+
jModel.MaxAttempts = (ev.RetryCount ?? 0) + 1;
|
|
132
|
+
try {
|
|
133
|
+
await jModel.insert();
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
// concurrent first-receipt from another worker won the insert; re-read and continue.
|
|
137
|
+
jModel = await JobModel.where({ JobId: ev.JobId }).firstOrThrow(new UnexpectedServerError(`No model found for jobId ${ev.JobId}`));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// at-least-once delivery means a job can be redelivered after it already finished
|
|
141
|
+
// ( consumer crash before ack, broker failover ). Skip re-running a job whose tracking
|
|
142
|
+
// row is already terminal so jobs stay idempotent. Acks without re-execution or rethrow.
|
|
143
|
+
if ((this.Configuration?.deduplicate ?? true) && JOB_TERMINAL_STATUSES.includes(jModel.Status)) {
|
|
144
|
+
this.Log.info(`Job ${ev.Name}:${ev.JobId} already in terminal state ${jModel.Status}, skipping duplicate delivery`);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
103
147
|
jModel.Status = 'executing';
|
|
104
148
|
jModel.ExecutedAt = DateTime.now();
|
|
149
|
+
// throttle progress persistence: skip writes smaller than the threshold and
|
|
150
|
+
// closer together than the min interval, so a chatty job doesn't hammer the DB.
|
|
151
|
+
let lastProgress = 0;
|
|
152
|
+
let lastProgressAt = 0;
|
|
153
|
+
const minProgressDelta = this.Configuration.progress?.minDelta ?? DEFAULT_PROGRESS_MIN_DELTA;
|
|
154
|
+
const minProgressInterval = this.Configuration.progress?.minInterval ?? DEFAULT_PROGRESS_MIN_INTERVAL_MS;
|
|
105
155
|
try {
|
|
106
156
|
// update executing state
|
|
107
157
|
await jModel.update();
|
|
@@ -114,13 +164,48 @@ let DefaultQueueService = class DefaultQueueService extends QueueService {
|
|
|
114
164
|
}
|
|
115
165
|
catch (err) {
|
|
116
166
|
this.Log.error(err, `Cannot execute job ${event.name}`);
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
jModel.
|
|
167
|
+
// record the failed attempt and mark the job retrying / dead so the
|
|
168
|
+
// transport can apply its retry-then-dead-letter policy ( re-thrown below ).
|
|
169
|
+
// the error goes to LastError - Result is reserved for the successful output.
|
|
170
|
+
jModel.Attempt = (jModel.Attempt ?? 0) + 1;
|
|
171
|
+
// derive the retry limit from the dispatch-time ceiling captured on the row so it stays
|
|
172
|
+
// authoritative across redeliveries ( a redelivered wire message could carry a different
|
|
173
|
+
// RetryCount ). MaxAttempts is retries + 1, so the limit is MaxAttempts - 1.
|
|
174
|
+
const maxRetries = jModel.MaxAttempts ? jModel.MaxAttempts - 1 : (ev.RetryCount ?? 0);
|
|
175
|
+
jModel.Status = jModel.Attempt > maxRetries ? 'dead' : 'retrying';
|
|
176
|
+
jModel.LastError = err instanceof Error ? err.message : String(err);
|
|
177
|
+
await jModel.update();
|
|
178
|
+
// notify the job of the failed attempt ( e.g. to send an alert on the final one ).
|
|
179
|
+
// the hook must never mask the original error, so its own failure is only logged.
|
|
180
|
+
try {
|
|
181
|
+
await ev.onFailed(err, { attempt: jModel.Attempt, maxAttempts: jModel.MaxAttempts ?? maxRetries + 1, isFinal: jModel.Status === 'dead', jobId: ev.JobId });
|
|
182
|
+
}
|
|
183
|
+
catch (hookErr) {
|
|
184
|
+
this.Log.error(hookErr, `onFailed hook for job ${event.name} threw`);
|
|
185
|
+
}
|
|
186
|
+
// propagate so the transport sees the failure and can retry / dead-letter.
|
|
187
|
+
// ( previously the error was swallowed and the message silently acked )
|
|
188
|
+
throw err;
|
|
121
189
|
}
|
|
122
190
|
await jModel.update();
|
|
123
|
-
async function onProgress(p) {
|
|
191
|
+
async function onProgress(p, meta) {
|
|
192
|
+
const now = DateTime.now().toMillis();
|
|
193
|
+
const isFinal = p >= 100;
|
|
194
|
+
const hasMeta = meta?.phase !== undefined || meta?.message !== undefined;
|
|
195
|
+
// apply meta eagerly so a phase / message change is never lost to throttling
|
|
196
|
+
if (meta?.phase !== undefined) {
|
|
197
|
+
jModel.Phase = meta.phase;
|
|
198
|
+
}
|
|
199
|
+
if (meta?.message !== undefined) {
|
|
200
|
+
jModel.Message = meta.message;
|
|
201
|
+
}
|
|
202
|
+
// always persist the final 100% or a meta change; otherwise throttle by delta + time
|
|
203
|
+
if (!isFinal && !hasMeta && p - lastProgress < minProgressDelta && now - lastProgressAt < minProgressInterval) {
|
|
204
|
+
jModel.Progress = p;
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
lastProgress = p;
|
|
208
|
+
lastProgressAt = now;
|
|
124
209
|
jModel.Progress = p;
|
|
125
210
|
await jModel.update();
|
|
126
211
|
self.Log.trace(`Job ${event.name}:${jModel.JobId} progress: ${p}%`);
|
|
@@ -154,6 +239,10 @@ __decorate([
|
|
|
154
239
|
AutoinjectService('queue.connections', QueueClient),
|
|
155
240
|
__metadata("design:type", Map)
|
|
156
241
|
], DefaultQueueService.prototype, "Connections", void 0);
|
|
242
|
+
__decorate([
|
|
243
|
+
AutoinjectService('queue.retention', JobRetentionService),
|
|
244
|
+
__metadata("design:type", JobRetentionService)
|
|
245
|
+
], DefaultQueueService.prototype, "Retention", void 0);
|
|
157
246
|
DefaultQueueService = __decorate([
|
|
158
247
|
Injectable(QueueService)
|
|
159
248
|
], DefaultQueueService);
|
package/lib/mjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAe,EAAE,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|