@zintrust/queue-monitor 0.4.49 → 0.4.60

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/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import { type RedisConfig } from './connection';
3
3
  import { type QueueDriver } from './driver';
4
4
  import { type Metrics } from './metrics';
5
5
  export type { JobPayload } from './driver';
6
+ export { createMetrics, type JobStatus, type JobSummary, type Metrics } from './metrics';
6
7
  export { createWorker as createQueueWorker, type QueueWorker } from './worker';
7
8
  export type QueueMonitorConfig = {
8
9
  enabled?: boolean;
@@ -11,6 +12,7 @@ export type QueueMonitorConfig = {
11
12
  autoRefresh?: boolean;
12
13
  refreshIntervalMs?: number;
13
14
  redis?: RedisConfig;
15
+ knownQueues?: ReadonlyArray<string> | (() => Promise<ReadonlyArray<string>> | ReadonlyArray<string>);
14
16
  };
15
17
  export type QueueCounts = {
16
18
  waiting: number;
package/dist/index.js CHANGED
@@ -1,9 +1,10 @@
1
- import { Logger, queueConfig, resolveLockPrefix, Router, } from '@zintrust/core';
1
+ import { isArray, isNonEmptyString, Logger, queueConfig, resolveLockPrefix, Router, } from '@zintrust/core';
2
2
  import { createRedisConnection } from './connection';
3
3
  import { getDashboardHtml } from './dashboard-ui';
4
4
  import { createBullMQDriver } from './driver';
5
5
  import { createMetrics } from './metrics';
6
- import { getRecentJobsForQueue, QueueMonitoringStream } from './QueueMonitoringService';
6
+ import { getRecentJobsForSelection, QueueMonitoringStream } from './QueueMonitoringService';
7
+ export { createMetrics } from './metrics';
7
8
  export { createWorker as createQueueWorker } from './worker';
8
9
  const DEFAULTS = {
9
10
  enabled: true,
@@ -34,6 +35,23 @@ const HISTOGRAM_BUCKETS = [
34
35
  { label: '>60m', min: 3_600_000 },
35
36
  ];
36
37
  const MAX_LOCK_KEYS = 10_000;
38
+ function normalizeQueueNames(queueNames) {
39
+ return Array.from(new Set(queueNames
40
+ .map((queueName) => queueName)
41
+ .filter(isNonEmptyString)
42
+ .map((name) => name.trim())))
43
+ .filter((name) => name.length > 0)
44
+ .sort((left, right) => left.localeCompare(right));
45
+ }
46
+ async function resolveKnownQueues(knownQueues) {
47
+ if (typeof knownQueues === 'function') {
48
+ return normalizeQueueNames(await knownQueues());
49
+ }
50
+ if (isArray(knownQueues)) {
51
+ return normalizeQueueNames(knownQueues);
52
+ }
53
+ return [];
54
+ }
37
55
  // Helper function to scan lock keys with pagination
38
56
  const scanLockKeys = async (client, searchPattern, maxKeys) => {
39
57
  const keys = [];
@@ -148,7 +166,7 @@ async function handleJobsEndpoint(req, res, metrics, driver) {
148
166
  res.status(400).json(fieldError('queue_name', 'Queue name must be provided'));
149
167
  return;
150
168
  }
151
- const jobs = await getRecentJobsForQueue(queueName, metrics, driver);
169
+ const jobs = await getRecentJobsForSelection(queueName, metrics, driver);
152
170
  res.json(jobs);
153
171
  }
154
172
  async function handleRetryEndpoint(req, res, driver) {
@@ -177,9 +195,13 @@ function buildSettings(config) {
177
195
  : DEFAULTS.refreshIntervalMs,
178
196
  };
179
197
  }
180
- function createGetSnapshot(driver, startedAt) {
198
+ function createGetSnapshot(driver, startedAt, knownQueues) {
181
199
  return async () => {
182
- const queues = await driver.getQueues();
200
+ const [discoveredQueues, persistedQueues] = await Promise.all([
201
+ driver.getQueues(),
202
+ resolveKnownQueues(knownQueues),
203
+ ]);
204
+ const queues = Array.from(new Set([...persistedQueues, ...discoveredQueues])).sort((left, right) => left.localeCompare(right));
183
205
  const stats = await Promise.all(queues.map(async (name) => {
184
206
  const counts = await driver.getJobCounts(name);
185
207
  return { name, counts: counts };
@@ -270,7 +292,7 @@ export const QueueMonitor = Object.freeze({
270
292
  const driver = createBullMQDriver(redisConfig);
271
293
  const metrics = createMetrics(redisConfig);
272
294
  const startedAt = new Date().toISOString();
273
- const getSnapshot = createGetSnapshot(driver, startedAt);
295
+ const getSnapshot = createGetSnapshot(driver, startedAt, config.knownQueues);
274
296
  const getLocks = createGetLocks(redisConfig);
275
297
  const registerRoutes = createRegisterRoutes(settings, metrics, driver, getSnapshot, getLocks);
276
298
  const close = async () => {
package/dist/metrics.d.ts CHANGED
@@ -4,6 +4,7 @@ export type JobStatus = 'completed' | 'failed';
4
4
  export type JobSummary = {
5
5
  id: string | undefined;
6
6
  name: string;
7
+ queue?: string;
7
8
  data: unknown;
8
9
  attempts: number;
9
10
  status?: string;
@@ -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,7 @@
1
+ export type WorkerUiOptions = {
2
+ basePath: string;
3
+ apiBaseUrl?: string;
4
+ autoRefresh: boolean;
5
+ refreshIntervalMs: number;
6
+ };
7
+ export declare const getWorkersHtml: (options: WorkerUiOptions) => string;