@zintrust/queue-monitor 2.0.0 → 2.1.3

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.
@@ -1,4 +1,4 @@
1
- import type { IRequest, IResponse } from '@zintrust/core';
1
+ import type { IRequest, IResponse } from '@zintrust/core/http';
2
2
  import type { QueueDriver } from './driver';
3
3
  import type { LockAnalytics, QueueMonitorSnapshot } from './index';
4
4
  import type { JobSummary, Metrics } from './metrics';
@@ -1,4 +1,4 @@
1
- import { Logger } from '@zintrust/core';
1
+ import { Logger } from '@zintrust/core/logger';
2
2
  export const ALL_QUEUES = '__all__';
3
3
  const subscriptions = new Map();
4
4
  const channels = new Map();
@@ -0,0 +1,20 @@
1
+ type WorkerApiResponse<T> = {
2
+ ok: boolean;
3
+ error?: string;
4
+ } & T;
5
+ export declare const WorkerClient: Readonly<{
6
+ listWorkers(): Promise<string[]>;
7
+ getWorker(name: string): Promise<unknown>;
8
+ getStatus(name: string): Promise<unknown>;
9
+ getHealth(name: string): Promise<unknown>;
10
+ startWorker(name: string): Promise<WorkerApiResponse<{
11
+ message?: string;
12
+ }>>;
13
+ stopWorker(name: string): Promise<WorkerApiResponse<{
14
+ message?: string;
15
+ }>>;
16
+ restartWorker(name: string): Promise<WorkerApiResponse<{
17
+ message?: string;
18
+ }>>;
19
+ }>;
20
+ export {};
@@ -0,0 +1,45 @@
1
+ import { ErrorFactory, Logger } from '@zintrust/core';
2
+ import { WorkerConfig } from '../config/workerConfig.js';
3
+ const requestJson = async (path, options = {}) => {
4
+ const baseUrl = WorkerConfig.getWorkerBaseUrl();
5
+ const url = `${baseUrl}${path}`;
6
+ const response = await fetch(url, {
7
+ ...options,
8
+ headers: {
9
+ 'Content-Type': 'application/json',
10
+ ...options.headers,
11
+ },
12
+ });
13
+ if (!response.ok) {
14
+ Logger.error('Worker API request failed', { url, status: response.status });
15
+ throw ErrorFactory.createWorkerError(`Worker API request failed (${response.status})`);
16
+ }
17
+ return (await response.json());
18
+ };
19
+ export const WorkerClient = Object.freeze({
20
+ async listWorkers() {
21
+ const response = await requestJson('/api/workers');
22
+ return response.workers ?? [];
23
+ },
24
+ async getWorker(name) {
25
+ const response = await requestJson(`/api/workers/${name}`);
26
+ return response.worker;
27
+ },
28
+ async getStatus(name) {
29
+ const response = await requestJson(`/api/workers/${name}/status`);
30
+ return response.status;
31
+ },
32
+ async getHealth(name) {
33
+ const response = await requestJson(`/api/workers/${name}/health`);
34
+ return response.health;
35
+ },
36
+ async startWorker(name) {
37
+ return requestJson(`/api/workers/${name}/start`, { method: 'POST' });
38
+ },
39
+ async stopWorker(name) {
40
+ return requestJson(`/api/workers/${name}/stop`, { method: 'POST' });
41
+ },
42
+ async restartWorker(name) {
43
+ return requestJson(`/api/workers/${name}/restart`, { method: 'POST' });
44
+ },
45
+ });
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@zintrust/queue-monitor",
3
- "version": "2.0.0",
4
- "buildDate": "2026-05-20T20:03:20.173Z",
3
+ "version": "2.1.3",
4
+ "buildDate": "2026-05-27T04:06:48.857Z",
5
5
  "buildEnvironment": {
6
- "node": "v20.20.2",
7
- "platform": "linux",
8
- "arch": "x64"
6
+ "node": "v22.22.1",
7
+ "platform": "darwin",
8
+ "arch": "arm64"
9
9
  },
10
10
  "git": {
11
- "commit": "be96835b",
12
- "branch": "master"
11
+ "commit": "c82f6263",
12
+ "branch": "release"
13
13
  },
14
14
  "package": {
15
15
  "engines": {
@@ -33,20 +33,56 @@
33
33
  "sha256": "33e57f6cec15b8dcb5886ca92644139d2e3ca1789aae1c3a4a066d75a273a6bb"
34
34
  },
35
35
  "QueueMonitoringService.d.ts": {
36
- "size": 1684,
37
- "sha256": "26a91f1b41d8a976a9e8fabaedc3fe6dc955c700499f0afc1a16fb91c9848665"
36
+ "size": 1689,
37
+ "sha256": "02c48a81818833e049fa8606014b0af2f8cbd04ec57f0be874873da24f72e2b9"
38
38
  },
39
39
  "QueueMonitoringService.js": {
40
- "size": 8928,
41
- "sha256": "fc408db720d5883821b169eabce66944295068cd6f2338f1884493c299f0a0f1"
40
+ "size": 8935,
41
+ "sha256": "c099e8922dd5642bce33a7db4b4a98641cab16e45a4ab76f989ef76a1178700e"
42
+ },
43
+ "api/workerClient.d.ts": {
44
+ "size": 597,
45
+ "sha256": "1d712bfa9127aa2df4f1fbd0efbb6d84069e1888ed73aca5542a41eee865d4bb"
46
+ },
47
+ "api/workerClient.js": {
48
+ "size": 1629,
49
+ "sha256": "60f993a42f4a9dd5000b01dae3b0f105a8f4348da8433a735b5cc1929a8f64ce"
50
+ },
51
+ "build-manifest.json": {
52
+ "size": 5228,
53
+ "sha256": "4950be04d3c30e53ac2abd01e6bfe05f6c3ffcdd7c7250f89fb067ad7db39896"
54
+ },
55
+ "config/queueMonitor.d.ts": {
56
+ "size": 407,
57
+ "sha256": "4541f47e64c8ede1bfd8fc0cb7edb76c4e885311b28b1f51c9be7639e5d87eca"
58
+ },
59
+ "config/queueMonitor.js": {
60
+ "size": 689,
61
+ "sha256": "0b95e6b65d4b6ffdd69788cdfd19e0e76400a39ad69dce018d8827a3b298e419"
62
+ },
63
+ "config/workerConfig.d.ts": {
64
+ "size": 86,
65
+ "sha256": "b669205d50c8844455a2d9b34a54f48a71118eb6ac99bad5372683ab666f5a22"
66
+ },
67
+ "config/workerConfig.js": {
68
+ "size": 628,
69
+ "sha256": "ca1c6dbaa751893f0e6b7c8a7fd41a80f7d5e8fc9aaaa4877ca12821bb25f56f"
42
70
  },
43
71
  "connection.d.ts": {
44
- "size": 285,
45
- "sha256": "02b8d856e6b905f10ac01fabe7c44560530878c0ec73924889e1d159018d317a"
72
+ "size": 287,
73
+ "sha256": "dcc6ea45e59b0a2e8844b27f466dff4849618c06b74aae62a99c8edd772d0db0"
46
74
  },
47
75
  "connection.js": {
48
- "size": 171,
49
- "sha256": "a4d2967491dc471a75c163f81b5c7199f9e3b34c7c958b65d5bc6bb11798fc6f"
76
+ "size": 178,
77
+ "sha256": "ff387351f5b8c7c14a7f2ef817fbbb065ad677faffcb47e5e8ddc4b064747e5b"
78
+ },
79
+ "dashboard-index.d.ts": {
80
+ "size": 180,
81
+ "sha256": "f78b4a0a83566640eca154f92d3f858ec41deb2521a500939ee3f0e58ee5db86"
82
+ },
83
+ "dashboard-index.js": {
84
+ "size": 183,
85
+ "sha256": "9d7c7fc63fe2919de0584d3f3d0ef74166d834af0a68caca2fe6fe64340652b9"
50
86
  },
51
87
  "dashboard-ui.d.ts": {
52
88
  "size": 219,
@@ -56,37 +92,77 @@
56
92
  "size": 53927,
57
93
  "sha256": "71bab126f20aea1165ee3aa3c82e896ebd89b1f1a815ef2716cd884b846ab34f"
58
94
  },
95
+ "driver-index.d.ts": {
96
+ "size": 280,
97
+ "sha256": "71a4dc5d823391fe16e966069aae8e6704d5c2d64aaceb447e138fdde7023690"
98
+ },
99
+ "driver-index.js": {
100
+ "size": 184,
101
+ "sha256": "fb91df973acd13a88cca443e50ecdd34944c66e1a1d48333f63099079a00f3c9"
102
+ },
59
103
  "driver.d.ts": {
60
104
  "size": 1102,
61
105
  "sha256": "70b74e7a0489da3a5545dfd8458ab5b4def1f3733c291a782c033fed0afd0bcf"
62
106
  },
63
107
  "driver.js": {
64
- "size": 5165,
65
- "sha256": "06a4aa4294ed0694146d184e8b0f1677ebe22a3d90bffa30b7c268657035c760"
108
+ "size": 5211,
109
+ "sha256": "e1ba94425ab8f00cb8c34fde73fa447fe239966f2e6484d470c09b23f0931c17"
66
110
  },
67
111
  "index.d.ts": {
68
- "size": 2161,
69
- "sha256": "2556c136641769f4e7cd81abd6ecae8663433aba74b09bc507b8fba01e3fc6f5"
112
+ "size": 2166,
113
+ "sha256": "384c5772e26ed721b5c0fffafe6a03f0385df8414058c9c944d742b4c0301ac4"
70
114
  },
71
115
  "index.js": {
72
- "size": 14399,
73
- "sha256": "18b28ec7b731fd8a68c05c008cbecfb59427c8bc157da938976b45c1adb117ad"
116
+ "size": 14603,
117
+ "sha256": "600478b203c190df631f01b04852d8e1e784bd7f18177b8a9218e99489ce527b"
118
+ },
119
+ "metrics-index.d.ts": {
120
+ "size": 233,
121
+ "sha256": "993ffe832f2914a81c81364f7b6d5c7247cd16da9bb9feb04caf8d770c14f9ec"
122
+ },
123
+ "metrics-index.js": {
124
+ "size": 171,
125
+ "sha256": "53e858995605858b819f2c48c701e3b8f7d028ec51c1b4814c46284c7fb3989e"
74
126
  },
75
127
  "metrics.d.ts": {
76
128
  "size": 910,
77
129
  "sha256": "6467795f6de818a1f295c42755005e394f25b145163c7678d6ac9ac1f9477fea"
78
130
  },
79
131
  "metrics.js": {
80
- "size": 3472,
81
- "sha256": "fab0e6d62ed694dcf57904a68b683280e4063c2fdcf97c60fdf5d933ae2b8f4f"
132
+ "size": 3478,
133
+ "sha256": "43cbce7fcf4db9c7e25806db716b6b20340fc29d0c29daec92bc40cc9f1e520d"
134
+ },
135
+ "routes/workers.d.ts": {
136
+ "size": 477,
137
+ "sha256": "cfcc3527c47d1a796a3ced2d4777b339dd767f7feb3ecc66c5ce0a91d8ff1bc8"
138
+ },
139
+ "routes/workers.js": {
140
+ "size": 901,
141
+ "sha256": "1ec48c0becc8c0628b1780fb400e957c5fe50da79f73112436c33ecde7d7d574"
142
+ },
143
+ "runtime-index.d.ts": {
144
+ "size": 2209,
145
+ "sha256": "e5d5c3475a7caec57f9e1a61bffb11038858e2c3f7be03e04ca28b8295e878fc"
146
+ },
147
+ "runtime-index.js": {
148
+ "size": 8924,
149
+ "sha256": "494757d540fe57507ac59ef2935ad683cb14fa57dbe188ffe3e6dd9fe3cb1ea9"
82
150
  },
83
151
  "worker.d.ts": {
84
152
  "size": 332,
85
153
  "sha256": "97cddbc991c6e6724950090cd92f06671932ab848c16dd94a030d9fba3fbae26"
86
154
  },
87
155
  "worker.js": {
88
- "size": 1233,
89
- "sha256": "da26c1b80da7473e1644a4e0f8d814097ce0adff14e36037164f9ae5855e656a"
156
+ "size": 1239,
157
+ "sha256": "46f116eb169fca1dc6dfd48d299001635c48a2da8d6e10115a98fcd33187b53e"
158
+ },
159
+ "workers-ui.d.ts": {
160
+ "size": 214,
161
+ "sha256": "4f5fd3bbd077d0dee2cc6c73d2c736fc52119b0d3a5f4a1878a4f3d3d3edf299"
162
+ },
163
+ "workers-ui.js": {
164
+ "size": 24928,
165
+ "sha256": "ba2c5cbf890fe875cc5336c76bd29b146089bc8ba3a70de4a2c383f395f9be73"
90
166
  }
91
167
  }
92
168
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Queue Monitor Configuration (default override)
3
+ *
4
+ * Keep this file declarative:
5
+ * - Core owns env parsing/default logic.
6
+ * - Projects can override config by editing values below.
7
+ */
8
+ declare const _default: {
9
+ enabled: boolean;
10
+ basePath: string;
11
+ middleware: string[];
12
+ redis: {
13
+ host: string;
14
+ port: number;
15
+ password: string;
16
+ };
17
+ };
18
+ export default _default;
@@ -0,0 +1,21 @@
1
+ import { Env } from '@zintrust/core';
2
+ /**
3
+ * Queue Monitor Configuration (default override)
4
+ *
5
+ * Keep this file declarative:
6
+ * - Core owns env parsing/default logic.
7
+ * - Projects can override config by editing values below.
8
+ */
9
+ export default {
10
+ enabled: Env.getBool('QUEUE_MONITOR_ENABLED', true),
11
+ basePath: Env.get('QUEUE_MONITOR_BASE_PATH', '/queue-monitor'),
12
+ middleware: Env.get('QUEUE_MONITOR_MIDDLEWARE', 'auth')
13
+ .split(',')
14
+ .map((m) => m.trim())
15
+ .filter((m) => m.length > 0),
16
+ redis: {
17
+ host: Env.get('REDIS_HOST', 'localhost'),
18
+ port: Env.getInt('REDIS_PORT', 6379),
19
+ password: Env.get('REDIS_PASSWORD', ''),
20
+ },
21
+ };
@@ -0,0 +1,3 @@
1
+ export declare const WorkerConfig: Readonly<{
2
+ getWorkerBaseUrl: () => string;
3
+ }>;
@@ -0,0 +1,19 @@
1
+ import { Env } from '@zintrust/core';
2
+ const normalizeBaseUrl = (value) => {
3
+ let end = value.length;
4
+ while (end > 0 && value.charAt(end - 1) === '/') {
5
+ end--;
6
+ }
7
+ return value.slice(0, end);
8
+ };
9
+ const withHttpScheme = (value) => value.startsWith('http://') || value.startsWith('https://') ? value : `http://${value}`;
10
+ const resolveWorkerApiUrl = () => {
11
+ const workerApiUrl = Env.get('WORKER_API_URL');
12
+ if (workerApiUrl) {
13
+ return normalizeBaseUrl(withHttpScheme(workerApiUrl));
14
+ }
15
+ return '';
16
+ };
17
+ export const WorkerConfig = Object.freeze({
18
+ getWorkerBaseUrl: resolveWorkerApiUrl,
19
+ });
@@ -1,3 +1,3 @@
1
- import { createRedisConnection as createCoreRedisConnection } from '@zintrust/core';
2
- export type { RedisConfig } from '@zintrust/core';
1
+ import { createRedisConnection as createCoreRedisConnection, type RedisConfig } from '@zintrust/core/redis';
2
+ export type { RedisConfig };
3
3
  export declare const createRedisConnection: (...args: Parameters<typeof createCoreRedisConnection>) => ReturnType<typeof createCoreRedisConnection>;
@@ -1,2 +1,2 @@
1
- import { createRedisConnection as createCoreRedisConnection } from '@zintrust/core';
1
+ import { createRedisConnection as createCoreRedisConnection, } from '@zintrust/core/redis';
2
2
  export const createRedisConnection = (...args) => createCoreRedisConnection(...args);
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Queue Monitor Dashboard UI - Non-runtime entrypoint
3
+ * Contains the dashboard UI components for development/admin use
4
+ */
5
+ export { getDashboardHtml } from './dashboard-ui';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Queue Monitor Dashboard UI - Non-runtime entrypoint
3
+ * Contains the dashboard UI components for development/admin use
4
+ */
5
+ export { getDashboardHtml } from './dashboard-ui';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Queue Monitor Driver - Runtime-only entrypoint
3
+ * Contains only the core queue driver functionality for production Workers
4
+ */
5
+ export type { JobPayload, JobCounts, RetrySnapshot, RetryJobResult, QueueDriver } from './driver';
6
+ export { createBullMQDriver } from './driver';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Queue Monitor Driver - Runtime-only entrypoint
3
+ * Contains only the core queue driver functionality for production Workers
4
+ */
5
+ export { createBullMQDriver } from './driver';
package/dist/driver.js CHANGED
@@ -1,4 +1,5 @@
1
- import { ErrorFactory, getBullMQSafeQueueName } from '@zintrust/core';
1
+ import { ErrorFactory } from '@zintrust/core/errors';
2
+ import { getBullMQSafeQueueName } from '@zintrust/core/redis';
2
3
  import { Queue } from 'bullmq';
3
4
  import { createRedisConnection } from './connection';
4
5
  async function enrichJobsWithState(jobs) {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type IRouter } from '@zintrust/core';
1
+ import { type IRouter } from '@zintrust/core/http';
2
2
  import { type RedisConfig } from './connection';
3
3
  import { type QueueDriver } from './driver';
4
4
  import { type Metrics } from './metrics';
package/dist/index.js CHANGED
@@ -1,4 +1,9 @@
1
- import { Env, isNonEmptyString, Logger, queueConfig, resolveLockPrefix, Router, ShutdownTrace, } from '@zintrust/core';
1
+ import { Env, queueConfig } from '@zintrust/core/config';
2
+ import { Router, } from '@zintrust/core/http';
3
+ import { Logger } from '@zintrust/core/logger';
4
+ import { resolveLockPrefix } from '@zintrust/core/queue';
5
+ import { isNonEmptyString } from '@zintrust/core/utils';
6
+ import { ShutdownTrace } from '@zintrust/core/workers';
2
7
  import { createRedisConnection } from './connection';
3
8
  import { getDashboardHtml } from './dashboard-ui';
4
9
  import { createBullMQDriver } from './driver';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Queue Monitor Metrics - Runtime-only entrypoint
3
+ * Contains only the metrics functionality for production Workers
4
+ */
5
+ export type { JobStatus, JobSummary, Metrics } from './metrics';
6
+ export { createMetrics } from './metrics';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Queue Monitor Metrics - Runtime-only entrypoint
3
+ * Contains only the metrics functionality for production Workers
4
+ */
5
+ export { createMetrics } from './metrics';
package/dist/metrics.js CHANGED
@@ -1,4 +1,4 @@
1
- import { RedisKeys } from '@zintrust/core';
1
+ import { RedisKeys } from '@zintrust/core/queue';
2
2
  import { createRedisConnection } from './connection';
3
3
  /**
4
4
  * Creates a queue monitoring key using singleton RedisKeys
@@ -0,0 +1,10 @@
1
+ import { type IRouter } from '@zintrust/core';
2
+ import { type WorkerUiOptions } from '../workers-ui';
3
+ type RouteOptions = {
4
+ middleware?: ReadonlyArray<string>;
5
+ } | undefined;
6
+ export declare const registerWorkerUiRoutes: (router: IRouter, options: WorkerUiOptions, routeOptions: RouteOptions) => void;
7
+ declare const _default: Readonly<{
8
+ registerWorkerUiRoutes: (router: IRouter, options: WorkerUiOptions, routeOptions: RouteOptions) => void;
9
+ }>;
10
+ export default _default;
@@ -0,0 +1,20 @@
1
+ import { Router } from '@zintrust/core';
2
+ import { WorkerConfig } from '../config/workerConfig.js';
3
+ import { getWorkersHtml } from '../workers-ui.js';
4
+ const registerWorkerUiPage = (router, options, routeOptions) => {
5
+ const handler = (_req, res) => {
6
+ res.html(getWorkersHtml({
7
+ basePath: options.basePath,
8
+ apiBaseUrl: WorkerConfig.getWorkerBaseUrl(),
9
+ autoRefresh: options.autoRefresh,
10
+ refreshIntervalMs: options.refreshIntervalMs,
11
+ }));
12
+ };
13
+ Router.get(router, `${options.basePath}/workers`, handler, routeOptions);
14
+ Router.get(router, '/workers', handler, routeOptions);
15
+ Router.get(router, '/workers/', handler, routeOptions);
16
+ };
17
+ export const registerWorkerUiRoutes = (router, options, routeOptions) => {
18
+ registerWorkerUiPage(router, options, routeOptions);
19
+ };
20
+ export default Object.freeze({ registerWorkerUiRoutes });
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Queue Monitor - Runtime-only entrypoint for production Workers
3
+ * Excludes dashboard UI components that are not needed for runtime
4
+ */
5
+ import { type RedisConfig } from './connection';
6
+ import { type QueueDriver } from './driver';
7
+ import { type Metrics } from './metrics';
8
+ export type { JobPayload } from './driver';
9
+ export { createMetrics, type JobStatus, type JobSummary, type Metrics } from './metrics';
10
+ export { createWorker as createQueueWorker, type QueueWorker } from './worker';
11
+ export type QueueMonitorConfig = {
12
+ enabled?: boolean;
13
+ basePath?: string;
14
+ middleware?: ReadonlyArray<string>;
15
+ autoRefresh?: boolean;
16
+ refreshIntervalMs?: number;
17
+ redis?: RedisConfig;
18
+ knownQueues?: ReadonlyArray<string> | (() => Promise<ReadonlyArray<string>> | ReadonlyArray<string>);
19
+ };
20
+ export type QueueCounts = {
21
+ waiting: number;
22
+ active: number;
23
+ completed: number;
24
+ failed: number;
25
+ delayed: number;
26
+ paused: number;
27
+ };
28
+ export type QueueMonitorSnapshot = {
29
+ status: 'ok';
30
+ startedAt: string;
31
+ queues: Array<{
32
+ name: string;
33
+ counts: QueueCounts;
34
+ }>;
35
+ };
36
+ export type LockSummary = {
37
+ key: string;
38
+ ttl?: number;
39
+ expires?: string;
40
+ };
41
+ export type LockMetrics = {
42
+ active: number;
43
+ attempts: number;
44
+ acquired: number;
45
+ collisions: number;
46
+ collisionRate: number;
47
+ };
48
+ export type LockHistogramBucket = {
49
+ label: string;
50
+ count: number;
51
+ };
52
+ export type LockAnalytics = {
53
+ locks: LockSummary[];
54
+ metrics: LockMetrics;
55
+ histogram: LockHistogramBucket[];
56
+ };
57
+ export type QueueMonitorApi = {
58
+ getSnapshot: () => Promise<QueueMonitorSnapshot>;
59
+ getLocks: (pattern?: string) => Promise<LockAnalytics>;
60
+ driver: QueueDriver;
61
+ metrics: Metrics;
62
+ close: () => Promise<void>;
63
+ };
64
+ export declare const QueueMonitor: Readonly<{
65
+ create(config: QueueMonitorConfig): QueueMonitorApi;
66
+ }>;
67
+ export default QueueMonitor;
68
+ export { createBullMQDriver } from './driver';
69
+ /**
70
+ * Package version and build metadata
71
+ * Available at runtime for debugging and health checks
72
+ */
73
+ export declare const _ZINTRUST_QUEUE_MONITOR_VERSION = "0.1.0";
74
+ export declare const _ZINTRUST_QUEUE_MONITOR_BUILD_DATE = "__BUILD_DATE__";