@rudderjs/horizon 4.0.0 → 4.1.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/boost/guidelines.md +10 -0
- package/dist/api/routes.d.ts +11 -4
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +102 -124
- package/dist/api/routes.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/routes.d.ts +22 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +47 -0
- package/dist/routes.js.map +1 -0
- package/dist/views/vanilla/Dashboard.d.ts +10 -0
- package/dist/views/vanilla/Dashboard.d.ts.map +1 -0
- package/dist/views/vanilla/Dashboard.js +86 -0
- package/dist/views/vanilla/Dashboard.js.map +1 -0
- package/dist/views/vanilla/FailedJobs.d.ts +6 -0
- package/dist/views/vanilla/FailedJobs.d.ts.map +1 -0
- package/dist/views/vanilla/FailedJobs.js +17 -0
- package/dist/views/vanilla/FailedJobs.js.map +1 -0
- package/dist/views/vanilla/Layout.d.ts +20 -0
- package/dist/views/vanilla/Layout.d.ts.map +1 -0
- package/dist/{ui/layout.js → views/vanilla/Layout.js} +11 -15
- package/dist/views/vanilla/Layout.js.map +1 -0
- package/dist/views/vanilla/Queues.d.ts +6 -0
- package/dist/views/vanilla/Queues.d.ts.map +1 -0
- package/dist/views/vanilla/Queues.js +54 -0
- package/dist/views/vanilla/Queues.js.map +1 -0
- package/dist/views/vanilla/RecentJobs.d.ts +6 -0
- package/dist/views/vanilla/RecentJobs.d.ts.map +1 -0
- package/dist/views/vanilla/RecentJobs.js +17 -0
- package/dist/views/vanilla/RecentJobs.js.map +1 -0
- package/dist/views/vanilla/Workers.d.ts +6 -0
- package/dist/views/vanilla/Workers.d.ts.map +1 -0
- package/dist/views/vanilla/Workers.js +60 -0
- package/dist/views/vanilla/Workers.js.map +1 -0
- package/dist/views/vanilla/_html.d.ts +28 -0
- package/dist/views/vanilla/_html.d.ts.map +1 -0
- package/dist/views/vanilla/_html.js +56 -0
- package/dist/views/vanilla/_html.js.map +1 -0
- package/dist/views/vanilla/_jobTable.d.ts +11 -0
- package/dist/views/vanilla/_jobTable.d.ts.map +1 -0
- package/dist/views/vanilla/_jobTable.js +89 -0
- package/dist/views/vanilla/_jobTable.js.map +1 -0
- package/dist/views/vanilla/index.d.ts +8 -0
- package/dist/views/vanilla/index.d.ts.map +1 -0
- package/dist/views/vanilla/index.js +8 -0
- package/dist/views/vanilla/index.js.map +1 -0
- package/package.json +3 -3
- package/dist/ui/layout.d.ts +0 -6
- package/dist/ui/layout.d.ts.map +0 -1
- package/dist/ui/layout.js.map +0 -1
- package/dist/ui/pages.d.ts +0 -6
- package/dist/ui/pages.d.ts.map +0 -1
- package/dist/ui/pages.js +0 -295
- package/dist/ui/pages.js.map +0 -1
package/boost/guidelines.md
CHANGED
|
@@ -11,6 +11,16 @@ Three collectors:
|
|
|
11
11
|
2. **MetricsCollector** — Periodically snapshots per-queue stats: throughput, wait time, runtime, pending/active/completed/failed counts
|
|
12
12
|
3. **WorkerCollector** — Reports current process as a worker with memory usage and job counts
|
|
13
13
|
|
|
14
|
+
### File Layout
|
|
15
|
+
|
|
16
|
+
- `src/index.ts` — `HorizonProvider`, `Horizon` facade, `HorizonRegistry`, public re-exports
|
|
17
|
+
- `src/types.ts` — `HorizonJob`, `QueueMetric`, `WorkerInfo`, `HorizonStorage`, `HorizonConfig`
|
|
18
|
+
- `src/storage.ts` — `MemoryStorage`, `SqliteStorage`
|
|
19
|
+
- `src/collectors/` — three collector classes (job, metrics, worker)
|
|
20
|
+
- `src/routes.ts` — `registerHorizonRoutes(storage, opts)` — UI + API route registration. Mirrors `@rudderjs/telescope`'s `registerTelescopeRoutes()`.
|
|
21
|
+
- `src/api/routes.ts` — pure handler functions (`getStats`, `listRecentJobs`, `retryJob`, `authMiddleware`, …) called from `routes.ts`. Holds no router calls.
|
|
22
|
+
- `src/views/vanilla/` — UI pages (one file per page): `Layout`, `Dashboard`, `RecentJobs`, `FailedJobs`, `Queues`, `Workers`, `_html` (auto-escape helper), `_jobTable` (shared table partial).
|
|
23
|
+
|
|
14
24
|
## Key Patterns
|
|
15
25
|
|
|
16
26
|
- `HorizonJob` records the full lifecycle: dispatchedAt, startedAt, completedAt, duration, exception
|
package/dist/api/routes.d.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import type { AppRequest, AppResponse, MiddlewareHandler } from '@rudderjs/contracts';
|
|
1
2
|
import type { HorizonStorage, HorizonConfig } from '../types.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export declare function
|
|
3
|
+
export declare function getStats(storage: HorizonStorage, _req: AppRequest, res: AppResponse): Promise<void>;
|
|
4
|
+
export declare function listRecentJobs(storage: HorizonStorage, req: AppRequest, res: AppResponse): Promise<void>;
|
|
5
|
+
export declare function listFailedJobs(storage: HorizonStorage, req: AppRequest, res: AppResponse): Promise<void>;
|
|
6
|
+
export declare function showJob(storage: HorizonStorage, req: AppRequest, res: AppResponse): Promise<void>;
|
|
7
|
+
export declare function retryJob(storage: HorizonStorage, req: AppRequest, res: AppResponse): Promise<void>;
|
|
8
|
+
export declare function deleteJob(storage: HorizonStorage, req: AppRequest, res: AppResponse): Promise<void>;
|
|
9
|
+
export declare function listQueues(storage: HorizonStorage, _req: AppRequest, res: AppResponse): Promise<void>;
|
|
10
|
+
export declare function showQueue(storage: HorizonStorage, req: AppRequest, res: AppResponse): Promise<void>;
|
|
11
|
+
export declare function listWorkers(storage: HorizonStorage, _req: AppRequest, res: AppResponse): Promise<void>;
|
|
12
|
+
export declare function authMiddleware(config: Pick<HorizonConfig, 'auth'>): MiddlewareHandler;
|
|
6
13
|
//# sourceMappingURL=routes.d.ts.map
|
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":"
|
|
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,CAOf;AAED,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,cAAc,EACvB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,cAAc,EACvB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAQf;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
|
@@ -1,131 +1,109 @@
|
|
|
1
1
|
import { QueueRegistry } from '@rudderjs/queue';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
]
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return;
|
|
2
|
+
// ─── Handlers ──────────────────────────────────────────────
|
|
3
|
+
//
|
|
4
|
+
// Pure handler functions invoked from `../routes.ts`. Kept separate from
|
|
5
|
+
// route registration so they can be reused or unit-tested without spinning
|
|
6
|
+
// up a router.
|
|
7
|
+
export async function getStats(storage, _req, res) {
|
|
8
|
+
const [total, pending, processing, completed, failed, metrics, workerList] = await Promise.all([
|
|
9
|
+
storage.jobCount(),
|
|
10
|
+
storage.jobCount('pending'),
|
|
11
|
+
storage.jobCount('processing'),
|
|
12
|
+
storage.jobCount('completed'),
|
|
13
|
+
storage.jobCount('failed'),
|
|
14
|
+
storage.currentMetrics(),
|
|
15
|
+
storage.workers(),
|
|
16
|
+
]);
|
|
17
|
+
res.json({
|
|
18
|
+
jobs: { total, pending, processing, completed, failed },
|
|
19
|
+
queues: metrics,
|
|
20
|
+
workers: workerList.length,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export async function listRecentJobs(storage, req, res) {
|
|
24
|
+
const jobs = await storage.recentJobs({
|
|
25
|
+
page: parseInt(req.query['page'] ?? '1', 10),
|
|
26
|
+
perPage: parseInt(req.query['per_page'] ?? '50', 10),
|
|
27
|
+
queue: req.query['queue'],
|
|
28
|
+
search: req.query['search'],
|
|
29
|
+
status: req.query['status'],
|
|
30
|
+
});
|
|
31
|
+
const total = await storage.jobCount();
|
|
32
|
+
res.json({ data: jobs, meta: { total } });
|
|
33
|
+
}
|
|
34
|
+
export async function listFailedJobs(storage, req, res) {
|
|
35
|
+
const jobs = await storage.failedJobs({
|
|
36
|
+
page: parseInt(req.query['page'] ?? '1', 10),
|
|
37
|
+
perPage: parseInt(req.query['per_page'] ?? '50', 10),
|
|
38
|
+
queue: req.query['queue'],
|
|
39
|
+
search: req.query['search'],
|
|
40
|
+
});
|
|
41
|
+
const total = await storage.jobCount('failed');
|
|
42
|
+
res.json({ data: jobs, meta: { total } });
|
|
43
|
+
}
|
|
44
|
+
export async function showJob(storage, req, res) {
|
|
45
|
+
const job = await storage.findJob(req.params['id'] ?? '');
|
|
46
|
+
if (!job) {
|
|
47
|
+
res.status(404).json({ message: 'Job not found.' });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
res.json({ data: job });
|
|
51
|
+
}
|
|
52
|
+
export async function retryJob(storage, req, res) {
|
|
53
|
+
const job = await storage.findJob(req.params['id'] ?? '');
|
|
54
|
+
if (!job) {
|
|
55
|
+
res.status(404).json({ message: 'Job not found.' });
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (job.status !== 'failed') {
|
|
59
|
+
res.status(422).json({ message: 'Only failed jobs can be retried.' });
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const adapter = QueueRegistry.get();
|
|
63
|
+
if (adapter?.retryFailed) {
|
|
64
|
+
await adapter.retryFailed(job.queue);
|
|
65
|
+
storage.updateJob(job.id, { status: 'pending', exception: null });
|
|
66
|
+
res.json({ message: 'Job queued for retry.' });
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
res.status(501).json({ message: 'Queue adapter does not support retry.' });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export async function deleteJob(storage, req, res) {
|
|
73
|
+
const job = await storage.findJob(req.params['id'] ?? '');
|
|
74
|
+
if (!job) {
|
|
75
|
+
res.status(404).json({ message: 'Job not found.' });
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
storage.deleteJob(job.id);
|
|
79
|
+
res.json({ message: 'Job deleted.' });
|
|
80
|
+
}
|
|
81
|
+
export async function listQueues(storage, _req, res) {
|
|
82
|
+
const metrics = await storage.currentMetrics();
|
|
83
|
+
res.json({ data: metrics });
|
|
84
|
+
}
|
|
85
|
+
export async function showQueue(storage, req, res) {
|
|
86
|
+
const queue = req.params['queue'] ?? 'default';
|
|
87
|
+
const since = new Date(Date.now() - 24 * 60 * 60 * 1000); // last 24h
|
|
88
|
+
const history = await storage.metrics(queue, since);
|
|
89
|
+
let live = null;
|
|
90
|
+
const adapter = QueueRegistry.get();
|
|
91
|
+
if (adapter?.status) {
|
|
92
|
+
try {
|
|
93
|
+
live = await adapter.status(queue);
|
|
95
94
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}, middleware);
|
|
99
|
-
// ── Queue-level metrics ──────────────────────────────────
|
|
100
|
-
router.get(`${prefix}/queues`, async (_req, res) => {
|
|
101
|
-
const metrics = await storage.currentMetrics();
|
|
102
|
-
res.json({ data: metrics });
|
|
103
|
-
}, middleware);
|
|
104
|
-
router.get(`${prefix}/queues/:queue`, async (req, res) => {
|
|
105
|
-
const queue = req.params['queue'] ?? 'default';
|
|
106
|
-
const since = new Date(Date.now() - 24 * 60 * 60 * 1000); // last 24h
|
|
107
|
-
const history = await storage.metrics(queue, since);
|
|
108
|
-
// Also get live stats from the adapter if available
|
|
109
|
-
let live = null;
|
|
110
|
-
const adapter = QueueRegistry.get();
|
|
111
|
-
if (adapter?.status) {
|
|
112
|
-
try {
|
|
113
|
-
live = await adapter.status(queue);
|
|
114
|
-
}
|
|
115
|
-
catch {
|
|
116
|
-
// Not available
|
|
117
|
-
}
|
|
95
|
+
catch {
|
|
96
|
+
// Not available
|
|
118
97
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}, middleware);
|
|
98
|
+
}
|
|
99
|
+
res.json({ queue, history, live });
|
|
100
|
+
}
|
|
101
|
+
export async function listWorkers(storage, _req, res) {
|
|
102
|
+
const workerList = await storage.workers();
|
|
103
|
+
res.json({ data: workerList });
|
|
126
104
|
}
|
|
127
|
-
// ─── Auth Middleware
|
|
128
|
-
function authMiddleware(config) {
|
|
105
|
+
// ─── Auth Middleware ───────────────────────────────────────
|
|
106
|
+
export function authMiddleware(config) {
|
|
129
107
|
return async (req, res, next) => {
|
|
130
108
|
if (config.auth) {
|
|
131
109
|
const allowed = await config.auth(req);
|
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;
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
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,EACvE,MAAM,YAAY,CAAA;AAInB,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,CAAA;AAC7G,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC3D,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,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAI1E,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;
|
|
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,EACvE,MAAM,YAAY,CAAA;AAInB,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,CAAA;AAC7G,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC3D,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,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAI1E,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;CAoD5B;AAID,OAAO,EAAE,qBAAqB,EAAE,KAAK,4BAA4B,EAAE,MAAM,aAAa,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { MemoryStorage, SqliteStorage } 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
|
-
import {
|
|
6
|
+
import { registerHorizonRoutes } from './routes.js';
|
|
7
7
|
import { defaultConfig, } from './types.js';
|
|
8
8
|
export { MemoryStorage, SqliteStorage } from './storage.js';
|
|
9
9
|
export { JobCollector } from './collectors/job.js';
|
|
@@ -104,8 +104,13 @@ export class HorizonProvider extends ServiceProvider {
|
|
|
104
104
|
jobCollector.register();
|
|
105
105
|
metricsCollector.register();
|
|
106
106
|
workerCollector.register();
|
|
107
|
-
// ── Register API routes
|
|
108
|
-
await
|
|
107
|
+
// ── Register UI + API routes ──────────────────────────
|
|
108
|
+
await registerHorizonRoutes(storage, {
|
|
109
|
+
path: resolved.path,
|
|
110
|
+
...(resolved.auth ? { auth: resolved.auth } : {}),
|
|
111
|
+
});
|
|
109
112
|
}
|
|
110
113
|
}
|
|
114
|
+
// ─── Public route helper ───────────────────────────────────
|
|
115
|
+
export { registerHorizonRoutes } from './routes.js';
|
|
111
116
|
//# 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,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/routes.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from '@rudderjs/contracts';
|
|
2
|
+
import type { HorizonStorage, HorizonConfig } from './types.js';
|
|
3
|
+
export interface RegisterHorizonRoutesOptions {
|
|
4
|
+
/** Path prefix for all horizon routes — default `/horizon` */
|
|
5
|
+
path?: string;
|
|
6
|
+
/** Auth gate — receives request, returns boolean. Same shape as `HorizonConfig.auth`. */
|
|
7
|
+
auth?: HorizonConfig['auth'];
|
|
8
|
+
/** Extra middleware to prepend to all routes */
|
|
9
|
+
middleware?: MiddlewareHandler[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Register all Horizon routes — UI pages and API endpoints. Called from
|
|
13
|
+
* `HorizonProvider.boot()` once the router peer is resolved.
|
|
14
|
+
*
|
|
15
|
+
* Mirrors the package-UI shape established by `@rudderjs/auth`'s
|
|
16
|
+
* `registerAuthRoutes()` and `@rudderjs/telescope`'s
|
|
17
|
+
* `registerTelescopeRoutes()`. Package-internal pages live under
|
|
18
|
+
* `views/vanilla/`, route registration is centralised here, the API
|
|
19
|
+
* handler implementations live in `api/routes.ts`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function registerHorizonRoutes(storage: HorizonStorage, opts?: RegisterHorizonRoutesOptions): Promise<void>;
|
|
22
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA2B,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACrF,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAO/D,MAAM,WAAW,4BAA4B;IAC3C,8DAA8D;IAC9D,IAAI,CAAC,EAAQ,MAAM,CAAA;IACnB,yFAAyF;IACzF,IAAI,CAAC,EAAQ,aAAa,CAAC,MAAM,CAAC,CAAA;IAClC,gDAAgD;IAChD,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAA;CACjC;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,cAAc,EACvB,IAAI,GAAK,4BAAiC,GACzC,OAAO,CAAC,IAAI,CAAC,CAmDf"}
|
package/dist/routes.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Dashboard, RecentJobs, FailedJobs, Queues, Workers } from './views/vanilla/index.js';
|
|
2
|
+
import { getStats, listRecentJobs, listFailedJobs, showJob, retryJob, deleteJob, listQueues, showQueue, listWorkers, authMiddleware, } from './api/routes.js';
|
|
3
|
+
/**
|
|
4
|
+
* Register all Horizon routes — UI pages and API endpoints. Called from
|
|
5
|
+
* `HorizonProvider.boot()` once the router peer is resolved.
|
|
6
|
+
*
|
|
7
|
+
* Mirrors the package-UI shape established by `@rudderjs/auth`'s
|
|
8
|
+
* `registerAuthRoutes()` and `@rudderjs/telescope`'s
|
|
9
|
+
* `registerTelescopeRoutes()`. Package-internal pages live under
|
|
10
|
+
* `views/vanilla/`, route registration is centralised here, the API
|
|
11
|
+
* handler implementations live in `api/routes.ts`.
|
|
12
|
+
*/
|
|
13
|
+
export async function registerHorizonRoutes(storage, opts = {}) {
|
|
14
|
+
let router;
|
|
15
|
+
try {
|
|
16
|
+
router = (await import('@rudderjs/router')).router;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return; // @rudderjs/router not installed — horizon routes disabled
|
|
20
|
+
}
|
|
21
|
+
const basePath = `/${(opts.path ?? 'horizon').replace(/^\/+/, '')}`;
|
|
22
|
+
const apiPrefix = `${basePath}/api`;
|
|
23
|
+
const middleware = [
|
|
24
|
+
...(opts.middleware ?? []),
|
|
25
|
+
...(opts.auth ? [authMiddleware({ auth: opts.auth })] : []),
|
|
26
|
+
];
|
|
27
|
+
const html = (_req, res, content) => {
|
|
28
|
+
res.header('Content-Type', 'text/html').send(content);
|
|
29
|
+
};
|
|
30
|
+
// ── UI Pages ─────────────────────────────────────────────
|
|
31
|
+
router.get(basePath, (r, s) => html(r, s, Dashboard({ basePath, apiPrefix })), middleware);
|
|
32
|
+
router.get(`${basePath}/jobs/recent`, (r, s) => html(r, s, RecentJobs({ basePath, apiPrefix })), middleware);
|
|
33
|
+
router.get(`${basePath}/jobs/failed`, (r, s) => html(r, s, FailedJobs({ basePath, apiPrefix })), middleware);
|
|
34
|
+
router.get(`${basePath}/queues`, (r, s) => html(r, s, Queues({ basePath, apiPrefix })), middleware);
|
|
35
|
+
router.get(`${basePath}/workers`, (r, s) => html(r, s, Workers({ basePath, apiPrefix })), middleware);
|
|
36
|
+
// ── API ──────────────────────────────────────────────────
|
|
37
|
+
router.get(`${apiPrefix}/stats`, (req, res) => getStats(storage, req, res), middleware);
|
|
38
|
+
router.get(`${apiPrefix}/jobs/recent`, (req, res) => listRecentJobs(storage, req, res), middleware);
|
|
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);
|
|
43
|
+
router.get(`${apiPrefix}/queues`, (req, res) => listQueues(storage, req, res), middleware);
|
|
44
|
+
router.get(`${apiPrefix}/queues/:queue`, (req, res) => showQueue(storage, req, res), middleware);
|
|
45
|
+
router.get(`${apiPrefix}/workers`, (req, res) => listWorkers(storage, req, res), middleware);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAC7F,OAAO,EACL,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EACtE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,GACnD,MAAM,iBAAiB,CAAA;AAWxB;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAuB,EACvB,OAAwC,EAAE;IAG1C,IAAI,MAA+C,CAAA;IACnD,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,MAAM,CAAA;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,OAAM,CAAC,2DAA2D;IACpE,CAAC;IAED,MAAM,QAAQ,GAAI,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAA;IACpE,MAAM,SAAS,GAAG,GAAG,QAAQ,MAAM,CAAA;IACnC,MAAM,UAAU,GAAwB;QACtC,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;QAC1B,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5D,CAAA;IAED,MAAM,IAAI,GAAG,CAAC,IAAgB,EAAE,GAAgB,EAAE,OAAe,EAAQ,EAAE;QACzE,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACvD,CAAC,CAAA;IAED,4DAA4D;IAC5D,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAa,EAAE,CAAc,EAAE,EAAE,CACrD,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;IAC7D,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,cAAc,EAAE,CAAC,CAAa,EAAE,CAAc,EAAE,EAAE,CACtE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;IAC9D,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,cAAc,EAAE,CAAC,CAAa,EAAE,CAAc,EAAE,EAAE,CACtE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;IAC9D,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,SAAS,EAAE,CAAC,CAAa,EAAE,CAAc,EAAE,EAAE,CACjE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;IAC1D,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,UAAU,EAAE,CAAC,CAAa,EAAE,CAAc,EAAE,EAAE,CAClE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;IAE3D,4DAA4D;IAC5D,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,QAAQ,EAAE,CAAC,GAAe,EAAE,GAAgB,EAAE,EAAE,CACrE,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,CAAA;IAC1C,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,cAAc,EAAE,CAAC,GAAe,EAAE,GAAgB,EAAE,EAAE,CAC3E,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,CAAA;IAChD,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,cAAc,EAAE,CAAC,GAAe,EAAE,GAAgB,EAAE,EAAE,CAC3E,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,CAAA;IAChD,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,WAAW,EAAE,CAAC,GAAe,EAAE,GAAgB,EAAE,EAAE,CACxE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,CAAA;IACzC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,iBAAiB,EAAE,CAAC,GAAe,EAAE,GAAgB,EAAE,EAAE,CAC/E,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,CAAA;IAC1C,MAAM,CAAC,MAAM,CAAC,GAAG,SAAS,WAAW,EAAE,CAAC,GAAe,EAAE,GAAgB,EAAE,EAAE,CAC3E,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,CAAA;IAC3C,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,SAAS,EAAE,CAAC,GAAe,EAAE,GAAgB,EAAE,EAAE,CACtE,UAAU,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,CAAA;IAC5C,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,gBAAgB,EAAE,CAAC,GAAe,EAAE,GAAgB,EAAE,EAAE,CAC7E,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,CAAA;IAC3C,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,UAAU,EAAE,CAAC,GAAe,EAAE,GAAgB,EAAE,EAAE,CACvE,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,CAAA;AAC/C,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface DashboardProps {
|
|
2
|
+
basePath: string;
|
|
3
|
+
apiPrefix: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Dashboard landing page — overview cards (job counts by status) and
|
|
7
|
+
* a queue-metrics table. Auto-refreshes every 10 seconds.
|
|
8
|
+
*/
|
|
9
|
+
export declare function Dashboard(props: DashboardProps): string;
|
|
10
|
+
//# sourceMappingURL=Dashboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dashboard.d.ts","sourceRoot":"","sources":["../../../src/views/vanilla/Dashboard.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAG,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAiFvD"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Layout } from './Layout.js';
|
|
2
|
+
/**
|
|
3
|
+
* Dashboard landing page — overview cards (job counts by status) and
|
|
4
|
+
* a queue-metrics table. Auto-refreshes every 10 seconds.
|
|
5
|
+
*/
|
|
6
|
+
export function Dashboard(props) {
|
|
7
|
+
const { basePath, apiPrefix } = props;
|
|
8
|
+
const body = `
|
|
9
|
+
<div x-data="dashboard()" x-init="load()" x-cloak>
|
|
10
|
+
<h2 class="text-xl font-bold mb-6">Dashboard</h2>
|
|
11
|
+
|
|
12
|
+
<!-- Stats Cards -->
|
|
13
|
+
<div class="grid grid-cols-2 md:grid-cols-5 gap-4 mb-8">
|
|
14
|
+
<div class="bg-white rounded-xl border border-gray-200 p-4 shadow-sm">
|
|
15
|
+
<div class="text-2xl font-bold" x-text="stats.jobs?.total || 0"></div>
|
|
16
|
+
<div class="text-sm text-gray-500">Total Jobs</div>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="bg-white rounded-xl border border-gray-200 p-4 shadow-sm">
|
|
19
|
+
<div class="text-2xl font-bold text-amber-600" x-text="stats.jobs?.pending || 0"></div>
|
|
20
|
+
<div class="text-sm text-gray-500">Pending</div>
|
|
21
|
+
</div>
|
|
22
|
+
<div class="bg-white rounded-xl border border-gray-200 p-4 shadow-sm">
|
|
23
|
+
<div class="text-2xl font-bold text-blue-600" x-text="stats.jobs?.processing || 0"></div>
|
|
24
|
+
<div class="text-sm text-gray-500">Processing</div>
|
|
25
|
+
</div>
|
|
26
|
+
<div class="bg-white rounded-xl border border-gray-200 p-4 shadow-sm">
|
|
27
|
+
<div class="text-2xl font-bold text-green-600" x-text="stats.jobs?.completed || 0"></div>
|
|
28
|
+
<div class="text-sm text-gray-500">Completed</div>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="bg-white rounded-xl border border-gray-200 p-4 shadow-sm">
|
|
31
|
+
<div class="text-2xl font-bold text-red-600" x-text="stats.jobs?.failed || 0"></div>
|
|
32
|
+
<div class="text-sm text-gray-500">Failed</div>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<!-- Queue Metrics -->
|
|
37
|
+
<div class="bg-white rounded-xl border border-gray-200 shadow-sm">
|
|
38
|
+
<div class="px-5 py-4 border-b border-gray-100 flex items-center justify-between">
|
|
39
|
+
<h3 class="text-sm font-semibold text-gray-700">Queue Metrics</h3>
|
|
40
|
+
<span class="text-xs text-gray-400" x-text="stats.workers + ' worker(s)'"></span>
|
|
41
|
+
</div>
|
|
42
|
+
<div class="overflow-x-auto">
|
|
43
|
+
<table class="w-full text-sm">
|
|
44
|
+
<thead class="bg-gray-50 text-gray-500 text-xs uppercase">
|
|
45
|
+
<tr>
|
|
46
|
+
<th class="px-5 py-3 text-left">Queue</th>
|
|
47
|
+
<th class="px-5 py-3 text-right">Throughput</th>
|
|
48
|
+
<th class="px-5 py-3 text-right">Wait Time</th>
|
|
49
|
+
<th class="px-5 py-3 text-right">Runtime</th>
|
|
50
|
+
<th class="px-5 py-3 text-right">Pending</th>
|
|
51
|
+
<th class="px-5 py-3 text-right">Failed</th>
|
|
52
|
+
</tr>
|
|
53
|
+
</thead>
|
|
54
|
+
<tbody class="divide-y divide-gray-100">
|
|
55
|
+
<template x-for="q in stats.queues || []" :key="q.queue">
|
|
56
|
+
<tr class="hover:bg-gray-50">
|
|
57
|
+
<td class="px-5 py-3 font-medium" x-text="q.queue"></td>
|
|
58
|
+
<td class="px-5 py-3 text-right" x-text="q.throughput + '/min'"></td>
|
|
59
|
+
<td class="px-5 py-3 text-right" x-text="q.waitTime + 'ms'"></td>
|
|
60
|
+
<td class="px-5 py-3 text-right" x-text="q.runtime + 'ms'"></td>
|
|
61
|
+
<td class="px-5 py-3 text-right text-amber-600" x-text="q.pending"></td>
|
|
62
|
+
<td class="px-5 py-3 text-right text-red-600" x-text="q.failed"></td>
|
|
63
|
+
</tr>
|
|
64
|
+
</template>
|
|
65
|
+
<tr x-show="!stats.queues?.length">
|
|
66
|
+
<td colspan="6" class="px-5 py-8 text-center text-gray-400">No queue data yet.</td>
|
|
67
|
+
</tr>
|
|
68
|
+
</tbody>
|
|
69
|
+
</table>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<div class="mt-4 text-center text-xs text-gray-400">Auto-refreshes every 10 seconds</div>
|
|
74
|
+
</div>
|
|
75
|
+
<script>
|
|
76
|
+
function dashboard() {
|
|
77
|
+
return {
|
|
78
|
+
stats: {},
|
|
79
|
+
async load() { await this.refresh(); setInterval(() => this.refresh(), 10000) },
|
|
80
|
+
async refresh() { this.stats = await fetch('${apiPrefix}/stats').then(r => r.json()) }
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
</script>`;
|
|
84
|
+
return Layout({ title: 'Dashboard', body, basePath, activePath: '/' });
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=Dashboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dashboard.js","sourceRoot":"","sources":["../../../src/views/vanilla/Dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAOpC;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAqB;IAC7C,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,CAAA;IAErC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wDAwEyC,SAAS;;;cAGnD,CAAA;IAEZ,OAAO,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAA;AACxE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FailedJobs.d.ts","sourceRoot":"","sources":["../../../src/views/vanilla/FailedJobs.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAG,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAezD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Layout } from './Layout.js';
|
|
2
|
+
import { jobTable, jobScript } from './_jobTable.js';
|
|
3
|
+
export function FailedJobs(props) {
|
|
4
|
+
const { basePath, apiPrefix } = props;
|
|
5
|
+
const body = `
|
|
6
|
+
<div x-data="jobList('failed')" x-init="load()" x-cloak>
|
|
7
|
+
<div class="flex items-center justify-between mb-6">
|
|
8
|
+
<h2 class="text-xl font-bold">Failed Jobs</h2>
|
|
9
|
+
<input type="text" x-model="search" @input.debounce.300ms="load()"
|
|
10
|
+
placeholder="Search..." class="text-sm border border-gray-300 rounded-lg px-3 py-1.5 focus:ring-2 focus:ring-teal-500 outline-none">
|
|
11
|
+
</div>
|
|
12
|
+
${jobTable()}
|
|
13
|
+
</div>
|
|
14
|
+
${jobScript(apiPrefix)}`;
|
|
15
|
+
return Layout({ title: 'Failed Jobs', body, basePath, activePath: '/jobs/failed' });
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=FailedJobs.js.map
|