@rudderjs/horizon 4.1.0 → 6.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.
- package/README.md +3 -2
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +11 -5
- package/dist/api/routes.js.map +1 -1
- package/dist/collectors/job.d.ts +15 -3
- package/dist/collectors/job.d.ts.map +1 -1
- package/dist/collectors/job.js +68 -69
- package/dist/collectors/job.js.map +1 -1
- package/dist/collectors/worker.d.ts.map +1 -1
- package/dist/collectors/worker.js +6 -0
- package/dist/collectors/worker.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +42 -6
- package/dist/index.js.map +1 -1
- package/dist/routes.js +3 -3
- package/dist/routes.js.map +1 -1
- package/dist/storage.d.ts +47 -7
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +391 -25
- package/dist/storage.js.map +1 -1
- package/dist/types.d.ts +23 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/dist/views/vanilla/_jobTable.d.ts.map +1 -1
- package/dist/views/vanilla/_jobTable.js +9 -7
- package/dist/views/vanilla/_jobTable.js.map +1 -1
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ import { Horizon } from '@rudderjs/horizon'
|
|
|
24
24
|
|
|
25
25
|
const jobs = await Horizon.recentJobs({ queue: 'emails', perPage: 25 })
|
|
26
26
|
const failed = await Horizon.failedJobs()
|
|
27
|
-
const job = await Horizon.findJob('job-id')
|
|
27
|
+
const job = await Horizon.findJob('emails', 'job-id')
|
|
28
28
|
const metrics = await Horizon.currentMetrics()
|
|
29
29
|
const workers = await Horizon.workers()
|
|
30
30
|
const count = await Horizon.jobCount('failed')
|
|
@@ -36,7 +36,7 @@ const count = await Horizon.jobCount('failed')
|
|
|
36
36
|
|--------|---------|-------------|
|
|
37
37
|
| `recentJobs(options?)` | `HorizonJob[]` | List recent jobs with optional filters |
|
|
38
38
|
| `failedJobs(options?)` | `HorizonJob[]` | List failed jobs |
|
|
39
|
-
| `findJob(id)` | `HorizonJob \| null` | Find a single job by
|
|
39
|
+
| `findJob(queue, id)` | `HorizonJob \| null` | Find a single job by `(queue, id)` — BullMQ ids are per-queue |
|
|
40
40
|
| `currentMetrics()` | `QueueMetric[]` | Latest metric snapshot per queue |
|
|
41
41
|
| `workers()` | `WorkerInfo[]` | All known workers and their status |
|
|
42
42
|
| `jobCount(status?)` | `number` | Count jobs, optionally by status |
|
|
@@ -85,3 +85,4 @@ Horizon serves a built-in UI at `/{path}` with pages for:
|
|
|
85
85
|
- Requires `@rudderjs/queue` for job lifecycle hooks.
|
|
86
86
|
- Peers: `@rudderjs/router` and `@rudderjs/middleware` for route registration.
|
|
87
87
|
- Auto-prune runs on a background interval (does not block the event loop).
|
|
88
|
+
- With BullMQ, `MetricsCollector` only registers in the worker process (set `RUDDERJS_QUEUE_WORKER=1` — `pnpm rudder queue:work` does this for you). The dashboard process serves `/horizon/api/queues` from the worker's last write. If the worker is offline the metrics tile freezes; jobs and failed tabs continue to work because they read live state from BullMQ.
|
package/dist/api/routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAErF,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAa,MAAM,aAAa,CAAA;AAQ3E,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAK,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CASf;AAED,wBAAsB,OAAO,CAC3B,OAAO,EAAE,cAAc,EACvB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAErF,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAa,MAAM,aAAa,CAAA;AAQ3E,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAK,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CASf;AAED,wBAAsB,OAAO,CAC3B,OAAO,EAAE,cAAc,EACvB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CASf;AAED,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,cAAc,EACvB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,cAAc,EACvB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAsB,UAAU,CAC9B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAK,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,cAAc,EACvB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAK,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAGf;AAID,wBAAgB,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG,iBAAiB,CAWrF"}
|
package/dist/api/routes.js
CHANGED
|
@@ -42,7 +42,9 @@ export async function listFailedJobs(storage, req, res) {
|
|
|
42
42
|
res.json({ data: jobs, meta: { total } });
|
|
43
43
|
}
|
|
44
44
|
export async function showJob(storage, req, res) {
|
|
45
|
-
const
|
|
45
|
+
const queue = req.params['queue'] ?? '';
|
|
46
|
+
const id = req.params['id'] ?? '';
|
|
47
|
+
const job = await storage.findJob(queue, id);
|
|
46
48
|
if (!job) {
|
|
47
49
|
res.status(404).json({ message: 'Job not found.' });
|
|
48
50
|
return;
|
|
@@ -50,7 +52,9 @@ export async function showJob(storage, req, res) {
|
|
|
50
52
|
res.json({ data: job });
|
|
51
53
|
}
|
|
52
54
|
export async function retryJob(storage, req, res) {
|
|
53
|
-
const
|
|
55
|
+
const queue = req.params['queue'] ?? '';
|
|
56
|
+
const id = req.params['id'] ?? '';
|
|
57
|
+
const job = await storage.findJob(queue, id);
|
|
54
58
|
if (!job) {
|
|
55
59
|
res.status(404).json({ message: 'Job not found.' });
|
|
56
60
|
return;
|
|
@@ -62,7 +66,7 @@ export async function retryJob(storage, req, res) {
|
|
|
62
66
|
const adapter = QueueRegistry.get();
|
|
63
67
|
if (adapter?.retryFailed) {
|
|
64
68
|
await adapter.retryFailed(job.queue);
|
|
65
|
-
storage.updateJob(job.id, { status: 'pending', exception: null });
|
|
69
|
+
storage.updateJob(job.queue, job.id, { status: 'pending', exception: null });
|
|
66
70
|
res.json({ message: 'Job queued for retry.' });
|
|
67
71
|
}
|
|
68
72
|
else {
|
|
@@ -70,12 +74,14 @@ export async function retryJob(storage, req, res) {
|
|
|
70
74
|
}
|
|
71
75
|
}
|
|
72
76
|
export async function deleteJob(storage, req, res) {
|
|
73
|
-
const
|
|
77
|
+
const queue = req.params['queue'] ?? '';
|
|
78
|
+
const id = req.params['id'] ?? '';
|
|
79
|
+
const job = await storage.findJob(queue, id);
|
|
74
80
|
if (!job) {
|
|
75
81
|
res.status(404).json({ message: 'Job not found.' });
|
|
76
82
|
return;
|
|
77
83
|
}
|
|
78
|
-
storage.deleteJob(job.id);
|
|
84
|
+
storage.deleteJob(job.queue, job.id);
|
|
79
85
|
res.json({ message: 'Job deleted.' });
|
|
80
86
|
}
|
|
81
87
|
export async function listQueues(storage, _req, res) {
|
package/dist/api/routes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAG/C,8DAA8D;AAC9D,EAAE;AACF,yEAAyE;AACzE,2EAA2E;AAC3E,eAAe;AAEf,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,OAAuB,EACvB,IAAmB,EACnB,GAAoB;IAEpB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC7F,OAAO,CAAC,QAAQ,EAAE;QAClB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC3B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC1B,OAAO,CAAC,cAAc,EAAE;QACxB,OAAO,CAAC,OAAO,EAAE;KAClB,CAAC,CAAA;IAEF,GAAG,CAAC,IAAI,CAAC;QACP,IAAI,EAAK,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE;QAC1D,MAAM,EAAG,OAAO;QAChB,OAAO,EAAE,UAAU,CAAC,MAAM;KAC3B,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAuB,EACvB,GAAmB,EACnB,GAAoB;IAEpB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;QACpC,IAAI,EAAK,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAQ,GAAG,EAAE,EAAE,CAAC;QACnD,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QACpD,KAAK,EAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;QAC3B,MAAM,EAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC5B,MAAM,EAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAA0B;KACtD,CAAC,CAAA;IACF,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAA;IACtC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAuB,EACvB,GAAmB,EACnB,GAAoB;IAEpB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;QACpC,IAAI,EAAK,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAQ,GAAG,EAAE,EAAE,CAAC;QACnD,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QACpD,KAAK,EAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;QAC3B,MAAM,EAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC;KAC7B,CAAC,CAAA;IACF,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC9C,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,OAAuB,EACvB,GAAmB,EACnB,GAAoB;IAEpB,MAAM,GAAG,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"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"}
|
package/dist/collectors/job.d.ts
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import type { HorizonStorage } from '../types.js';
|
|
2
|
+
import type { MetricsCollector } from './metrics.js';
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
4
|
+
* Subscribes to `@rudderjs/queue/observers` and forwards lifecycle events
|
|
5
|
+
* into Horizon's storage. Replaces the legacy `dispatch()` monkey-patch
|
|
6
|
+
* which couldn't see worker-process events under BullMQ.
|
|
7
|
+
*
|
|
8
|
+
* The previous monkey-patch wrapped `job.handle` on an in-memory instance
|
|
9
|
+
* the worker process never received via Redis — so worker-side
|
|
10
|
+
* completed/failed transitions were lost. The observer surface emits in
|
|
11
|
+
* the worker process, RedisStorage propagates the writes back to the
|
|
12
|
+
* dashboard process. See `docs/plans/2026-05-01-horizon-bullmq-fix.md`.
|
|
5
13
|
*/
|
|
6
14
|
export declare class JobCollector {
|
|
7
15
|
private readonly storage;
|
|
16
|
+
private readonly metricsCollector;
|
|
8
17
|
readonly name = "Job Collector";
|
|
9
|
-
|
|
18
|
+
private unsubscribe;
|
|
19
|
+
constructor(storage: HorizonStorage, metricsCollector?: MetricsCollector | null);
|
|
10
20
|
register(): void;
|
|
21
|
+
/** @internal — used in tests + provider shutdown. */
|
|
22
|
+
unregister(): void;
|
|
11
23
|
}
|
|
12
24
|
//# sourceMappingURL=job.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../../src/collectors/job.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../../src/collectors/job.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,aAAa,CAAA;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEpD;;;;;;;;;;GAUG;AACH,qBAAa,YAAY;IAKrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IALnC,QAAQ,CAAC,IAAI,mBAAkB;IAC/B,OAAO,CAAC,WAAW,CAA4B;gBAG5B,OAAO,EAAW,cAAc,EAChC,gBAAgB,GAAE,gBAAgB,GAAG,IAAW;IAGnE,QAAQ,IAAI,IAAI;IA4DhB,qDAAqD;IACrD,UAAU,IAAI,IAAI;CAInB"}
|
package/dist/collectors/job.js
CHANGED
|
@@ -1,85 +1,84 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { QueueRegistry } from '@rudderjs/queue';
|
|
1
|
+
import { queueObservers } from '@rudderjs/queue/observers';
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Subscribes to `@rudderjs/queue/observers` and forwards lifecycle events
|
|
4
|
+
* into Horizon's storage. Replaces the legacy `dispatch()` monkey-patch
|
|
5
|
+
* which couldn't see worker-process events under BullMQ.
|
|
6
|
+
*
|
|
7
|
+
* The previous monkey-patch wrapped `job.handle` on an in-memory instance
|
|
8
|
+
* the worker process never received via Redis — so worker-side
|
|
9
|
+
* completed/failed transitions were lost. The observer surface emits in
|
|
10
|
+
* the worker process, RedisStorage propagates the writes back to the
|
|
11
|
+
* dashboard process. See `docs/plans/2026-05-01-horizon-bullmq-fix.md`.
|
|
6
12
|
*/
|
|
7
13
|
export class JobCollector {
|
|
8
14
|
storage;
|
|
15
|
+
metricsCollector;
|
|
9
16
|
name = 'Job Collector';
|
|
10
|
-
|
|
17
|
+
unsubscribe = null;
|
|
18
|
+
constructor(storage, metricsCollector = null) {
|
|
11
19
|
this.storage = storage;
|
|
20
|
+
this.metricsCollector = metricsCollector;
|
|
12
21
|
}
|
|
13
22
|
register() {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const originalDispatch = adapter.dispatch.bind(adapter);
|
|
19
|
-
adapter['dispatch'] = async (job, options) => {
|
|
20
|
-
const id = randomUUID();
|
|
21
|
-
const name = job.constructor.name;
|
|
22
|
-
const queue = options?.queue ?? job.constructor['queue'] ?? 'default';
|
|
23
|
-
const now = new Date();
|
|
24
|
-
// Record dispatch
|
|
25
|
-
const record = {
|
|
26
|
-
id,
|
|
27
|
-
name,
|
|
28
|
-
queue,
|
|
29
|
-
status: 'pending',
|
|
30
|
-
payload: safeSerialize(job),
|
|
31
|
-
attempts: 0,
|
|
32
|
-
exception: null,
|
|
33
|
-
dispatchedAt: now,
|
|
34
|
-
startedAt: null,
|
|
35
|
-
completedAt: null,
|
|
36
|
-
duration: null,
|
|
37
|
-
tags: [`job:${name}`, `queue:${queue}`],
|
|
38
|
-
};
|
|
39
|
-
storage.recordJob(record);
|
|
40
|
-
// Track start/complete/fail via wrapping the job's handle method
|
|
41
|
-
const originalHandle = job.handle.bind(job);
|
|
42
|
-
const originalFailed = job.failed?.bind(job);
|
|
43
|
-
job.handle = async () => {
|
|
44
|
-
const startedAt = new Date();
|
|
45
|
-
storage.updateJob(id, { status: 'processing', startedAt, attempts: record.attempts + 1 });
|
|
23
|
+
this.unsubscribe = queueObservers.subscribe((event) => {
|
|
24
|
+
// Storage writes can be async (Redis); fire-and-forget but trap rejects
|
|
25
|
+
// so a transient Redis blip never escapes into the queue layer.
|
|
26
|
+
void Promise.resolve().then(async () => {
|
|
46
27
|
try {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
28
|
+
switch (event.kind) {
|
|
29
|
+
case 'job.dispatched': {
|
|
30
|
+
const record = {
|
|
31
|
+
id: event.jobId,
|
|
32
|
+
name: event.name,
|
|
33
|
+
queue: event.queue,
|
|
34
|
+
status: 'pending',
|
|
35
|
+
payload: event.payload,
|
|
36
|
+
attempts: 0,
|
|
37
|
+
exception: null,
|
|
38
|
+
dispatchedAt: event.dispatchedAt,
|
|
39
|
+
startedAt: null,
|
|
40
|
+
completedAt: null,
|
|
41
|
+
duration: null,
|
|
42
|
+
tags: [`job:${event.name}`, `queue:${event.queue}`],
|
|
43
|
+
};
|
|
44
|
+
await this.storage.recordJob(record);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
case 'job.active':
|
|
48
|
+
await this.storage.updateJob(event.queue, event.jobId, {
|
|
49
|
+
status: 'processing',
|
|
50
|
+
startedAt: event.startedAt,
|
|
51
|
+
attempts: event.attempts,
|
|
52
|
+
});
|
|
53
|
+
break;
|
|
54
|
+
case 'job.completed':
|
|
55
|
+
await this.storage.updateJob(event.queue, event.jobId, {
|
|
56
|
+
status: 'completed',
|
|
57
|
+
completedAt: event.completedAt,
|
|
58
|
+
duration: event.duration,
|
|
59
|
+
});
|
|
60
|
+
this.metricsCollector?.recordJobCompleted(event.queue, event.startedAt.getTime() - event.dispatchedAt.getTime(), event.duration);
|
|
61
|
+
break;
|
|
62
|
+
case 'job.failed':
|
|
63
|
+
await this.storage.updateJob(event.queue, event.jobId, {
|
|
64
|
+
status: 'failed',
|
|
65
|
+
completedAt: event.completedAt,
|
|
66
|
+
...(event.duration !== undefined ? { duration: event.duration } : {}),
|
|
67
|
+
exception: event.error,
|
|
68
|
+
});
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
51
71
|
}
|
|
52
72
|
catch (err) {
|
|
53
|
-
|
|
54
|
-
const duration = completedAt.getTime() - startedAt.getTime();
|
|
55
|
-
storage.updateJob(id, {
|
|
56
|
-
status: 'failed',
|
|
57
|
-
completedAt,
|
|
58
|
-
duration,
|
|
59
|
-
exception: err instanceof Error ? err.message : String(err),
|
|
60
|
-
});
|
|
61
|
-
throw err;
|
|
73
|
+
console.warn('[Horizon] storage write failed:', err instanceof Error ? err.message : String(err));
|
|
62
74
|
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
job.failed = async (error) => {
|
|
66
|
-
storage.updateJob(id, {
|
|
67
|
-
status: 'failed',
|
|
68
|
-
exception: error instanceof Error ? error.message : String(error),
|
|
69
|
-
});
|
|
70
|
-
await originalFailed(error);
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
await originalDispatch(job, options);
|
|
74
|
-
};
|
|
75
|
+
});
|
|
76
|
+
});
|
|
75
77
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
catch {
|
|
82
|
-
return {};
|
|
78
|
+
/** @internal — used in tests + provider shutdown. */
|
|
79
|
+
unregister() {
|
|
80
|
+
this.unsubscribe?.();
|
|
81
|
+
this.unsubscribe = null;
|
|
83
82
|
}
|
|
84
83
|
}
|
|
85
84
|
//# sourceMappingURL=job.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job.js","sourceRoot":"","sources":["../../src/collectors/job.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"job.js","sourceRoot":"","sources":["../../src/collectors/job.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAI1D;;;;;;;;;;GAUG;AACH,MAAM,OAAO,YAAY;IAKJ;IACA;IALV,IAAI,GAAG,eAAe,CAAA;IACvB,WAAW,GAAwB,IAAI,CAAA;IAE/C,YACmB,OAAgC,EAChC,mBAA4C,IAAI;QADhD,YAAO,GAAP,OAAO,CAAyB;QAChC,qBAAgB,GAAhB,gBAAgB,CAAgC;IAChE,CAAC;IAEJ,QAAQ;QACN,IAAI,CAAC,WAAW,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;YACpD,wEAAwE;YACxE,gEAAgE;YAChE,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;gBACrC,IAAI,CAAC;oBACH,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;wBACnB,KAAK,gBAAgB,CAAC,CAAC,CAAC;4BACtB,MAAM,MAAM,GAAe;gCACzB,EAAE,EAAY,KAAK,CAAC,KAAK;gCACzB,IAAI,EAAU,KAAK,CAAC,IAAI;gCACxB,KAAK,EAAS,KAAK,CAAC,KAAK;gCACzB,MAAM,EAAQ,SAAS;gCACvB,OAAO,EAAO,KAAK,CAAC,OAAO;gCAC3B,QAAQ,EAAM,CAAC;gCACf,SAAS,EAAK,IAAI;gCAClB,YAAY,EAAE,KAAK,CAAC,YAAY;gCAChC,SAAS,EAAK,IAAI;gCAClB,WAAW,EAAG,IAAI;gCAClB,QAAQ,EAAM,IAAI;gCAClB,IAAI,EAAU,CAAC,OAAO,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,KAAK,CAAC,KAAK,EAAE,CAAC;6BAC5D,CAAA;4BACD,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;4BACpC,MAAK;wBACP,CAAC;wBACD,KAAK,YAAY;4BACf,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;gCACrD,MAAM,EAAK,YAAY;gCACvB,SAAS,EAAE,KAAK,CAAC,SAAS;gCAC1B,QAAQ,EAAG,KAAK,CAAC,QAAQ;6BAC1B,CAAC,CAAA;4BACF,MAAK;wBACP,KAAK,eAAe;4BAClB,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;gCACrD,MAAM,EAAO,WAAW;gCACxB,WAAW,EAAE,KAAK,CAAC,WAAW;gCAC9B,QAAQ,EAAK,KAAK,CAAC,QAAQ;6BAC5B,CAAC,CAAA;4BACF,IAAI,CAAC,gBAAgB,EAAE,kBAAkB,CACvC,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,EACxD,KAAK,CAAC,QAAQ,CACf,CAAA;4BACD,MAAK;wBACP,KAAK,YAAY;4BACf,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;gCACrD,MAAM,EAAO,QAAQ;gCACrB,WAAW,EAAE,KAAK,CAAC,WAAW;gCAC9B,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gCACrE,SAAS,EAAI,KAAK,CAAC,KAAK;6BACzB,CAAC,CAAA;4BACF,MAAK;oBACT,CAAC;gBACH,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,IAAI,CAAC,iCAAiC,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;gBACnG,CAAC;YACH,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,qDAAqD;IACrD,UAAU;QACR,IAAI,CAAC,WAAW,EAAE,EAAE,CAAA;QACpB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAA;IACzB,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/collectors/worker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,aAAa,CAAA;AAE7D;;;GAGG;AACH,qBAAa,eAAe;IAOxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAPxB,QAAQ,CAAC,IAAI,sBAAqB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,OAAO,CAAI;IACnB,OAAO,CAAC,SAAS,CAAoB;gBAGlB,OAAO,EAAE,cAAc,EACvB,KAAK,GAAE,MAAkB;IAK5C,QAAQ,IAAI,IAAI;
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/collectors/worker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,aAAa,CAAA;AAE7D;;;GAGG;AACH,qBAAa,eAAe;IAOxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAPxB,QAAQ,CAAC,IAAI,sBAAqB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,OAAO,CAAI;IACnB,OAAO,CAAC,SAAS,CAAoB;gBAGlB,OAAO,EAAE,cAAc,EACvB,KAAK,GAAE,MAAkB;IAK5C,QAAQ,IAAI,IAAI;IAehB,kDAAkD;IAClD,kBAAkB,IAAI,IAAI;IAK1B,OAAO,CAAC,MAAM;CAaf"}
|
|
@@ -16,6 +16,12 @@ export class WorkerCollector {
|
|
|
16
16
|
this.workerId = `worker-${randomUUID().slice(0, 8)}`;
|
|
17
17
|
}
|
|
18
18
|
register() {
|
|
19
|
+
// Only register as a worker when running in an actual worker process.
|
|
20
|
+
// Set by `@rudderjs/queue-bullmq` (and any future self-hosted adapter)
|
|
21
|
+
// before booting `Worker` instances. Skipping in the dev/web process
|
|
22
|
+
// prevents the dashboard from listing itself as a worker.
|
|
23
|
+
if (process.env['RUDDERJS_QUEUE_WORKER'] !== '1')
|
|
24
|
+
return;
|
|
19
25
|
// Report initial status
|
|
20
26
|
this.report('active');
|
|
21
27
|
// Periodically update
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/collectors/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGxC;;;GAGG;AACH,MAAM,OAAO,eAAe;IAOP;IACA;IAPV,IAAI,GAAG,kBAAkB,CAAA;IACjB,QAAQ,CAAQ;IACzB,OAAO,GAAG,CAAC,CAAA;IACX,SAAS,GAAgB,IAAI,CAAA;IAErC,YACmB,OAAuB,EACvB,QAAgB,SAAS;QADzB,YAAO,GAAP,OAAO,CAAgB;QACvB,UAAK,GAAL,KAAK,CAAoB;QAE1C,IAAI,CAAC,QAAQ,GAAG,UAAU,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAA;IACtD,CAAC;IAED,QAAQ;QACN,wBAAwB;QACxB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAErB,sBAAsB;QACtB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAA;QAC9D,KAAK,CAAC,KAAK,EAAE,CAAA;IACf,CAAC;IAED,kDAAkD;IAClD,kBAAkB;QAChB,IAAI,CAAC,OAAO,EAAE,CAAA;QACd,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAA;IAC7B,CAAC;IAEO,MAAM,CAAC,MAA4B;QACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;QACtC,MAAM,IAAI,GAAe;YACvB,EAAE,EAAS,IAAI,CAAC,QAAQ;YACxB,KAAK,EAAM,IAAI,CAAC,KAAK;YACrB,MAAM;YACN,OAAO,EAAI,IAAI,CAAC,OAAO;YACvB,QAAQ,EAAG,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG;YACpE,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAA;QACD,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/collectors/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGxC;;;GAGG;AACH,MAAM,OAAO,eAAe;IAOP;IACA;IAPV,IAAI,GAAG,kBAAkB,CAAA;IACjB,QAAQ,CAAQ;IACzB,OAAO,GAAG,CAAC,CAAA;IACX,SAAS,GAAgB,IAAI,CAAA;IAErC,YACmB,OAAuB,EACvB,QAAgB,SAAS;QADzB,YAAO,GAAP,OAAO,CAAgB;QACvB,UAAK,GAAL,KAAK,CAAoB;QAE1C,IAAI,CAAC,QAAQ,GAAG,UAAU,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAA;IACtD,CAAC;IAED,QAAQ;QACN,sEAAsE;QACtE,uEAAuE;QACvE,qEAAqE;QACrE,0DAA0D;QAC1D,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,KAAK,GAAG;YAAE,OAAM;QAExD,wBAAwB;QACxB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAErB,sBAAsB;QACtB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAA;QAC9D,KAAK,CAAC,KAAK,EAAE,CAAA;IACf,CAAC;IAED,kDAAkD;IAClD,kBAAkB;QAChB,IAAI,CAAC,OAAO,EAAE,CAAA;QACd,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAA;IAC7B,CAAC;IAEO,MAAM,CAAC,MAA4B;QACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;QACtC,MAAM,IAAI,GAAe;YACvB,EAAE,EAAS,IAAI,CAAC,QAAQ;YACxB,KAAK,EAAM,IAAI,CAAC,KAAK;YACrB,MAAM;YACN,OAAO,EAAI,IAAI,CAAC,OAAO;YACvB,QAAQ,EAAG,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG;YACpE,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAA;QACD,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ServiceProvider } from '@rudderjs/core';
|
|
2
|
-
import { type HorizonConfig, type HorizonStorage, type HorizonJob, type QueueMetric, type WorkerInfo, type JobStatus, type JobListOptions } from './types.js';
|
|
3
|
-
export type { HorizonConfig, HorizonStorage, HorizonJob, QueueMetric, WorkerInfo, JobStatus, JobListOptions };
|
|
4
|
-
export { MemoryStorage, SqliteStorage } from './storage.js';
|
|
2
|
+
import { type HorizonConfig, type HorizonStorage, type HorizonJob, type QueueMetric, type WorkerInfo, type JobStatus, type JobListOptions, type HorizonRedisConfig } from './types.js';
|
|
3
|
+
export type { HorizonConfig, HorizonStorage, HorizonJob, QueueMetric, WorkerInfo, JobStatus, JobListOptions, HorizonRedisConfig };
|
|
4
|
+
export { MemoryStorage, SqliteStorage, RedisStorage } from './storage.js';
|
|
5
5
|
export { JobCollector } from './collectors/job.js';
|
|
6
6
|
export { MetricsCollector } from './collectors/metrics.js';
|
|
7
7
|
export { WorkerCollector } from './collectors/worker.js';
|
|
@@ -16,7 +16,7 @@ export declare class Horizon {
|
|
|
16
16
|
private static store;
|
|
17
17
|
static recentJobs(options?: JobListOptions): HorizonJob[] | Promise<HorizonJob[]>;
|
|
18
18
|
static failedJobs(options?: JobListOptions): HorizonJob[] | Promise<HorizonJob[]>;
|
|
19
|
-
static findJob(id: string): HorizonJob | null | Promise<HorizonJob | null>;
|
|
19
|
+
static findJob(queue: string, id: string): HorizonJob | null | Promise<HorizonJob | null>;
|
|
20
20
|
static currentMetrics(): QueueMetric[] | Promise<QueueMetric[]>;
|
|
21
21
|
static workers(): WorkerInfo[] | Promise<WorkerInfo[]>;
|
|
22
22
|
static jobCount(status?: JobStatus): number | Promise<number>;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAU,MAAM,gBAAgB,CAAA;AAMxD,OAAO,EAEL,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EACxD,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAU,MAAM,gBAAgB,CAAA;AAMxD,OAAO,EAEL,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EACxD,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,cAAc,EACtE,KAAK,kBAAkB,EACxB,MAAM,YAAY,CAAA;AAInB,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAA;AACjI,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAIxD,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,OAAO,CAA8B;IAEpD,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IACzC,MAAM,CAAC,GAAG,IAAI,cAAc,GAAG,IAAI;IACnC,mEAAmE;IACnE,MAAM,CAAC,KAAK,IAAI,IAAI;CACrB;AAID,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAC,KAAK;IAMpB,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAIjF,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAIjF,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAIzF,MAAM,CAAC,cAAc,IAAI,WAAW,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAI/D,MAAM,CAAC,OAAO,IAAI,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAItD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAG9D;AAID;;;;;;;;;;GAUG;AACH,qBAAa,eAAgB,SAAQ,eAAe;IAClD,QAAQ,IAAI,IAAI;IAQV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAoF5B;AAID,OAAO,EAAE,qBAAqB,EAAE,KAAK,4BAA4B,EAAE,MAAM,aAAa,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ServiceProvider, config } from '@rudderjs/core';
|
|
2
|
-
import { MemoryStorage, SqliteStorage } from './storage.js';
|
|
2
|
+
import { MemoryStorage, SqliteStorage, RedisStorage } from './storage.js';
|
|
3
3
|
import { JobCollector } from './collectors/job.js';
|
|
4
4
|
import { MetricsCollector } from './collectors/metrics.js';
|
|
5
5
|
import { WorkerCollector } from './collectors/worker.js';
|
|
6
6
|
import { registerHorizonRoutes } from './routes.js';
|
|
7
7
|
import { defaultConfig, } from './types.js';
|
|
8
|
-
export { MemoryStorage, SqliteStorage } from './storage.js';
|
|
8
|
+
export { MemoryStorage, SqliteStorage, RedisStorage } from './storage.js';
|
|
9
9
|
export { JobCollector } from './collectors/job.js';
|
|
10
10
|
export { MetricsCollector } from './collectors/metrics.js';
|
|
11
11
|
export { WorkerCollector } from './collectors/worker.js';
|
|
@@ -31,8 +31,8 @@ export class Horizon {
|
|
|
31
31
|
static failedJobs(options) {
|
|
32
32
|
return this.store().failedJobs(options);
|
|
33
33
|
}
|
|
34
|
-
static findJob(id) {
|
|
35
|
-
return this.store().findJob(id);
|
|
34
|
+
static findJob(queue, id) {
|
|
35
|
+
return this.store().findJob(queue, id);
|
|
36
36
|
}
|
|
37
37
|
static currentMetrics() {
|
|
38
38
|
return this.store().currentMetrics();
|
|
@@ -83,11 +83,29 @@ export class HorizonProvider extends ServiceProvider {
|
|
|
83
83
|
if (resolved.storage === 'sqlite') {
|
|
84
84
|
storage = new SqliteStorage(resolved.sqlitePath);
|
|
85
85
|
}
|
|
86
|
+
else if (resolved.storage === 'redis') {
|
|
87
|
+
const redisCfg = (cfg.redis ?? defaultConfig.redis);
|
|
88
|
+
storage = new RedisStorage(redisCfg, resolved.maxJobs);
|
|
89
|
+
}
|
|
86
90
|
else {
|
|
87
91
|
storage = new MemoryStorage(resolved.maxJobs);
|
|
88
92
|
}
|
|
89
93
|
HorizonRegistry.set(storage);
|
|
90
94
|
this.app.instance('horizon', storage);
|
|
95
|
+
// ── Misconfig warning ─────────────────────────────────
|
|
96
|
+
// BullMQ runs jobs in a separate process; with in-memory storage the
|
|
97
|
+
// dashboard can't see the worker-process state transitions and every
|
|
98
|
+
// job appears stuck at 'pending' forever. Surface this loudly so users
|
|
99
|
+
// catch it before they're staring at a dead dashboard.
|
|
100
|
+
try {
|
|
101
|
+
const queueDriver = config('queue', {})?.default;
|
|
102
|
+
if (queueDriver === 'bullmq' && resolved.storage === 'memory') {
|
|
103
|
+
console.warn('[Horizon] queue driver "bullmq" is paired with horizon storage "memory" — ' +
|
|
104
|
+
'the dashboard will not see worker-process events (jobs will appear stuck at pending). ' +
|
|
105
|
+
"Set horizon.storage = 'redis' in config/horizon.ts to fix this.");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch { /* config read failure shouldn't block boot */ }
|
|
91
109
|
// ── Auto-prune ────────────────────────────────────────
|
|
92
110
|
const pruneHours = resolved.pruneAfterHours;
|
|
93
111
|
if (pruneHours > 0) {
|
|
@@ -98,11 +116,29 @@ export class HorizonProvider extends ServiceProvider {
|
|
|
98
116
|
timer.unref();
|
|
99
117
|
}
|
|
100
118
|
// ── Register collectors ───────────────────────────────
|
|
101
|
-
const jobCollector = new JobCollector(storage);
|
|
102
119
|
const metricsCollector = new MetricsCollector(storage, resolved.metricsIntervalMs);
|
|
120
|
+
const jobCollector = new JobCollector(storage, metricsCollector);
|
|
103
121
|
const workerCollector = new WorkerCollector(storage);
|
|
104
122
|
jobCollector.register();
|
|
105
|
-
|
|
123
|
+
// For out-of-process queues (BullMQ), `queueObservers` events fire in
|
|
124
|
+
// the worker process, not the dashboard. Letting both processes poll
|
|
125
|
+
// `MetricsCollector.collect()` makes the dashboard write
|
|
126
|
+
// `throughput: 0` rows that clobber the worker's real counts via the
|
|
127
|
+
// shared Redis history ZSet. Gate to the worker process. Sync queue
|
|
128
|
+
// is in-process — dashboard IS the worker, so we let it through.
|
|
129
|
+
const queueDriver = (() => {
|
|
130
|
+
try {
|
|
131
|
+
return config('queue', {})?.default;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
})();
|
|
137
|
+
const outOfProcessQueue = queueDriver === 'bullmq';
|
|
138
|
+
const isWorkerProcess = process.env['RUDDERJS_QUEUE_WORKER'] === '1';
|
|
139
|
+
if (!outOfProcessQueue || isWorkerProcess) {
|
|
140
|
+
metricsCollector.register();
|
|
141
|
+
}
|
|
106
142
|
workerCollector.register();
|
|
107
143
|
// ── Register UI + API routes ──────────────────────────
|
|
108
144
|
await registerHorizonRoutes(storage, {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/routes.js
CHANGED
|
@@ -37,9 +37,9 @@ export async function registerHorizonRoutes(storage, opts = {}) {
|
|
|
37
37
|
router.get(`${apiPrefix}/stats`, (req, res) => getStats(storage, req, res), middleware);
|
|
38
38
|
router.get(`${apiPrefix}/jobs/recent`, (req, res) => listRecentJobs(storage, req, res), middleware);
|
|
39
39
|
router.get(`${apiPrefix}/jobs/failed`, (req, res) => listFailedJobs(storage, req, res), middleware);
|
|
40
|
-
router.get(`${apiPrefix}/jobs/:id`, (req, res) => showJob(storage, req, res), middleware);
|
|
41
|
-
router.post(`${apiPrefix}/jobs/:id/retry`, (req, res) => retryJob(storage, req, res), middleware);
|
|
42
|
-
router.delete(`${apiPrefix}/jobs/:id`, (req, res) => deleteJob(storage, req, res), middleware);
|
|
40
|
+
router.get(`${apiPrefix}/jobs/:queue/:id`, (req, res) => showJob(storage, req, res), middleware);
|
|
41
|
+
router.post(`${apiPrefix}/jobs/:queue/:id/retry`, (req, res) => retryJob(storage, req, res), middleware);
|
|
42
|
+
router.delete(`${apiPrefix}/jobs/:queue/:id`, (req, res) => deleteJob(storage, req, res), middleware);
|
|
43
43
|
router.get(`${apiPrefix}/queues`, (req, res) => listQueues(storage, req, res), middleware);
|
|
44
44
|
router.get(`${apiPrefix}/queues/:queue`, (req, res) => showQueue(storage, req, res), middleware);
|
|
45
45
|
router.get(`${apiPrefix}/workers`, (req, res) => listWorkers(storage, req, res), middleware);
|
package/dist/routes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
|
package/dist/storage.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { HorizonStorage, HorizonJob, QueueMetric, WorkerInfo, JobListOptions, JobStatus } from './types.js';
|
|
1
|
+
import type { HorizonStorage, HorizonJob, QueueMetric, WorkerInfo, JobListOptions, JobStatus, HorizonRedisConfig } from './types.js';
|
|
2
2
|
export declare class MemoryStorage implements HorizonStorage {
|
|
3
3
|
private readonly maxJobs;
|
|
4
4
|
private readonly jobs;
|
|
@@ -7,16 +7,16 @@ export declare class MemoryStorage implements HorizonStorage {
|
|
|
7
7
|
private readonly workerMap;
|
|
8
8
|
constructor(maxJobs?: number);
|
|
9
9
|
recordJob(job: HorizonJob): void;
|
|
10
|
-
updateJob(id: string, updates: Partial<HorizonJob>): void;
|
|
10
|
+
updateJob(queue: string, id: string, updates: Partial<HorizonJob>): void;
|
|
11
11
|
recentJobs(options?: JobListOptions): HorizonJob[];
|
|
12
12
|
failedJobs(options?: JobListOptions): HorizonJob[];
|
|
13
|
-
findJob(id: string): HorizonJob | null;
|
|
13
|
+
findJob(queue: string, id: string): HorizonJob | null;
|
|
14
14
|
recordMetric(metric: QueueMetric): void;
|
|
15
15
|
metrics(queue: string, since: Date): QueueMetric[];
|
|
16
16
|
currentMetrics(): QueueMetric[];
|
|
17
17
|
recordWorker(worker: WorkerInfo): void;
|
|
18
18
|
workers(): WorkerInfo[];
|
|
19
|
-
deleteJob(id: string): void;
|
|
19
|
+
deleteJob(queue: string, id: string): void;
|
|
20
20
|
pruneOlderThan(date: Date): void;
|
|
21
21
|
jobCount(status?: JobStatus): number;
|
|
22
22
|
private filterJobs;
|
|
@@ -28,20 +28,60 @@ export declare class SqliteStorage implements HorizonStorage {
|
|
|
28
28
|
private getDb;
|
|
29
29
|
private migrate;
|
|
30
30
|
recordJob(job: HorizonJob): void;
|
|
31
|
-
updateJob(id: string, updates: Partial<HorizonJob>): void;
|
|
31
|
+
updateJob(queue: string, id: string, updates: Partial<HorizonJob>): void;
|
|
32
32
|
recentJobs(options?: JobListOptions): HorizonJob[];
|
|
33
33
|
failedJobs(options?: JobListOptions): HorizonJob[];
|
|
34
|
-
findJob(id: string): HorizonJob | null;
|
|
34
|
+
findJob(queue: string, id: string): HorizonJob | null;
|
|
35
35
|
recordMetric(metric: QueueMetric): void;
|
|
36
36
|
metrics(queue: string, since: Date): QueueMetric[];
|
|
37
37
|
currentMetrics(): QueueMetric[];
|
|
38
38
|
recordWorker(worker: WorkerInfo): void;
|
|
39
39
|
workers(): WorkerInfo[];
|
|
40
|
-
deleteJob(id: string): void;
|
|
40
|
+
deleteJob(queue: string, id: string): void;
|
|
41
41
|
pruneOlderThan(date: Date): void;
|
|
42
42
|
jobCount(status?: JobStatus): number;
|
|
43
43
|
private queryJobs;
|
|
44
44
|
private jobFromRow;
|
|
45
45
|
private metricFromRow;
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Cross-process job/metric/worker store backed by Redis. Works alongside
|
|
49
|
+
* BullMQ's own Redis instance (separate connection by default) so the dev
|
|
50
|
+
* server and worker process share state.
|
|
51
|
+
*
|
|
52
|
+
* Falls back to memory if `ioredis` cannot be imported — the boot warning
|
|
53
|
+
* surfaces the misconfig.
|
|
54
|
+
*/
|
|
55
|
+
export declare class RedisStorage implements HorizonStorage {
|
|
56
|
+
private readonly config;
|
|
57
|
+
private readonly maxJobs;
|
|
58
|
+
private client;
|
|
59
|
+
private readonly prefix;
|
|
60
|
+
constructor(config?: HorizonRedisConfig, maxJobs?: number);
|
|
61
|
+
private getClient;
|
|
62
|
+
private connectionOpts;
|
|
63
|
+
private k;
|
|
64
|
+
private member;
|
|
65
|
+
private parseMember;
|
|
66
|
+
recordJob(job: HorizonJob): Promise<void>;
|
|
67
|
+
updateJob(queue: string, id: string, updates: Partial<HorizonJob>): Promise<void>;
|
|
68
|
+
recentJobs(options?: JobListOptions): Promise<HorizonJob[]>;
|
|
69
|
+
failedJobs(options?: JobListOptions): Promise<HorizonJob[]>;
|
|
70
|
+
findJob(queue: string, id: string): Promise<HorizonJob | null>;
|
|
71
|
+
deleteJob(queue: string, id: string): Promise<void>;
|
|
72
|
+
pruneOlderThan(date: Date): Promise<void>;
|
|
73
|
+
jobCount(status?: JobStatus): Promise<number>;
|
|
74
|
+
recordMetric(metric: QueueMetric): Promise<void>;
|
|
75
|
+
metrics(queue: string, since: Date): Promise<QueueMetric[]>;
|
|
76
|
+
currentMetrics(): Promise<QueueMetric[]>;
|
|
77
|
+
recordWorker(worker: WorkerInfo): Promise<void>;
|
|
78
|
+
workers(): Promise<WorkerInfo[]>;
|
|
79
|
+
/** @internal — close the Redis connection. Used in tests + shutdown. */
|
|
80
|
+
disconnect(): Promise<void>;
|
|
81
|
+
private jobToHash;
|
|
82
|
+
private jobFromHash;
|
|
83
|
+
private metricToHash;
|
|
84
|
+
private metricFromHash;
|
|
85
|
+
private listJobs;
|
|
86
|
+
}
|
|
47
87
|
//# sourceMappingURL=storage.d.ts.map
|