glide-mq 0.4.2 → 0.5.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/.jules/bolt.md ADDED
@@ -0,0 +1,3 @@
1
+ ## 2024-05-23 - [Worker Polling Loop Saturation]
2
+ **Learning:** The worker used a fixed 5ms sleep loop when saturated (`activeCount >= prefetch`). This caused unnecessary CPU usage (waking up 200 times/sec) just to check capacity.
3
+ **Action:** Replaced busy-wait with an event-driven mechanism using an internal `EventEmitter`. The loop now waits for a `slotFree` event (emitted when a job completes) or a 100ms safety timeout. This reduces CPU usage and improves responsiveness when slots open up.
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # glide-mq
2
2
 
3
- High-performance message queue for Node.js, built on Valkey/Redis Streams with [Valkey GLIDE](https://github.com/valkey-io/valkey-glide) native NAPI bindings.
3
+ High-performance message queue for Node.js Streams-first, native NAPI bindings, cloud-native by default.
4
+
5
+ Built on [Valkey Streams](https://valkey.io) + consumer groups with [Valkey GLIDE](https://github.com/valkey-io/valkey-glide)'s Rust core. Single function library instead of 53 EVAL scripts. 1 RTT per job.
4
6
 
5
7
  ## Performance
6
8
 
@@ -13,7 +15,7 @@ High-performance message queue for Node.js, built on Valkey/Redis Streams with [
13
15
  | c=10 | 15,504 jobs/s |
14
16
  | c=50 | 48,077 jobs/s |
15
17
 
16
- ### Bulk add (addBulk with Batch API)
18
+ ### Bulk add (`addBulk` via Batch API)
17
19
 
18
20
  | Jobs | Serial | Batch | Speedup |
19
21
  |------|--------|-------|---------|
@@ -24,21 +26,22 @@ High-performance message queue for Node.js, built on Valkey/Redis Streams with [
24
26
 
25
27
  | Mode | Stored size (15KB payload) | Savings |
26
28
  |------|--------------------------|---------|
27
- | Plain | 15,327 bytes | - |
29
+ | Plain | 15,327 bytes | |
28
30
  | Gzip | 331 bytes | 98% |
29
31
 
30
- No-op processor, Valkey 8.0, single node.
32
+ *No-op processor, Valkey 8.0, single node.*
31
33
 
32
- ## Why
34
+ ## Why glide-mq
33
35
 
34
- - **Streams-first** - Redis Streams + consumer groups + PEL instead of Lists + BRPOPLPUSH. Fewer moving parts, built-in at-least-once delivery.
35
- - **Server Functions** - single `FUNCTION LOAD` instead of dozens of EVAL scripts. Persistent across restarts, no NOSCRIPT cache-miss errors.
36
- - **1 RTT per job** - `completeAndFetchNext` combines job completion + next job fetch + activation in a single FCALL round trip.
37
- - **Cluster-native** - hash-tagged keys from day one. No afterthought `{braces}` requirement.
38
- - **Native bindings** - built on [@glidemq/speedkey](https://github.com/avifenesh/speedkey) (valkey-glide with Rust core + NAPI).
39
- - **AZ-Affinity** - route reads to same-AZ replicas, reducing cross-AZ latency and AWS costs by up to 75%.
40
- - **Batch pipelining** - `addBulk` uses GLIDE's Batch API for single round-trip bulk operations (12.7x faster than serial).
41
- - **Transparent compression** - gzip payloads with zero-config decompression on workers (98% savings on repetitive data).
36
+ | Feature | glide-mq | Traditional queue |
37
+ |---------|----------|-------------------|
38
+ | Queue backend | Streams + PEL | Lists + BRPOPLPUSH |
39
+ | Server scripts | 1 function library | 53 EVAL scripts |
40
+ | RTT per job | 1 (`completeAndFetchNext`) | 2+ |
41
+ | Cluster support | Built-in hash tags | Afterthought `{braces}` |
42
+ | Client | NAPI Rust core | ioredis |
43
+ | AZ-Affinity | | |
44
+ | IAM auth | ✓ | ✗ |
42
45
 
43
46
  ## Install
44
47
 
@@ -46,7 +49,7 @@ No-op processor, Valkey 8.0, single node.
46
49
  npm install glide-mq
47
50
  ```
48
51
 
49
- Requires Node.js 20+ and a running Valkey (7.0+) or Redis (7.0+) instance for FUNCTION support.
52
+ Requires Node.js 20+ and a running Valkey (7.0+) or Redis (7.0+) instance.
50
53
 
51
54
  ## Quick Start
52
55
 
@@ -61,312 +64,22 @@ await queue.add('send-email', { to: 'user@example.com', subject: 'Hello' });
61
64
 
62
65
  // Consumer
63
66
  const worker = new Worker('tasks', async (job) => {
64
- console.log(`Processing ${job.name}: ${JSON.stringify(job.data)}`);
67
+ console.log(`Processing ${job.name}:`, job.data);
65
68
  return { sent: true };
66
69
  }, { connection, concurrency: 10 });
67
70
 
68
- worker.on('completed', (job) => console.log(`Job ${job.id} completed`));
69
- worker.on('failed', (job, err) => console.log(`Job ${job.id} failed: ${err.message}`));
70
- ```
71
-
72
- ## Features
73
-
74
- ### Core
75
- - **Queue** - add, addBulk, getJob, getJobs, pause, resume, obliterate, drain
76
- - **Worker** - concurrent processing, XREADGROUP polling, graceful shutdown
77
- - **Job** - progress, updateData, retry, remove, log, state queries, waitUntilFinished
78
-
79
- ### Reliability
80
- - **Retries** - fixed, exponential, jitter backoff + custom strategy functions
81
- - **Stalled recovery** - XAUTOCLAIM with heartbeat-based lock renewal
82
- - **Per-job timeout** - automatic failure if processor exceeds timeout
83
- - **Dead letter queue** - permanently failed jobs routed to a separate queue
84
-
85
- ### Advanced
86
- - **Deduplication** - simple, throttle, debounce modes
87
- - **Rate limiting** - sliding window, per-queue
88
- - **Global concurrency** - limit active jobs across all workers
89
- - **Job retention** - removeOnComplete/removeOnFail (count, age-based)
90
- - **Priorities** - encoded in sorted set scores, FIFO within same priority
91
- - **Compression** - transparent gzip for job payloads (Node.js zlib, zero deps)
92
-
93
- ### Workflows
94
- - **FlowProducer** - atomic parent-child job trees with nested flows
95
- - **chain(queue, jobs)** - sequential pipeline, each job receives previous result
96
- - **group(queue, jobs)** - parallel execution, parent completes when all children done
97
- - **chord(queue, group, callback)** - run group, then callback with all results
98
-
99
- ### Observability
100
- - **QueueEvents** - stream-based event subscription (added, completed, failed, stalled, etc.)
101
- - **Job schedulers** - cron patterns and fixed intervals for repeatable jobs
102
- - **Metrics** - getJobCounts, getMetrics
103
- - **OpenTelemetry** - automatic tracing spans for Queue.add and FlowProducer.add operations (optional peer dependency)
104
-
105
- ### Cloud-Native (GLIDE-exclusive)
106
- - **AZ-Affinity routing** - route reads to same-AZ replicas for lower latency and reduced cross-AZ costs
107
- - **IAM authentication** - native AWS ElastiCache/MemoryDB auth with auto-token refresh
108
- - **Batch API** - single round-trip bulk operations via GLIDE's non-atomic pipeline
109
- - **Multiplexed connections** - single connection per node instead of connection pools
110
-
111
- ### Operations
112
- - **Graceful shutdown** - SIGTERM/SIGINT handler, waits for active jobs
113
- - **Connection recovery** - exponential backoff reconnect with function library reload
114
- - **Job revocation** - cooperative cancellation via AbortSignal
115
- - **Cluster mode** - all features work in Valkey Cluster (pass `clusterMode: true`)
116
-
117
- ## API
118
-
119
- ### Queue
120
-
121
- ```typescript
122
- const queue = new Queue('name', {
123
- connection: {
124
- addresses: [{ host, port }],
125
- clusterMode: false,
126
- readFrom: ReadFrom.AZAffinity, // route reads to same-AZ replicas
127
- clientAz: 'us-east-1a',
128
- credentials: { password: 'secret' },
129
- // or IAM: { type: 'iam', serviceType: 'elasticache', region: 'us-east-1', userId: 'user', clusterName: 'my-cluster' }
130
- },
131
- prefix: 'glide',
132
- compression: 'gzip', // transparent payload compression
133
- });
134
-
135
- await queue.add('jobName', data, {
136
- delay: 5000, // delayed job (ms)
137
- priority: 1, // lower = higher priority
138
- attempts: 3, // max retry attempts
139
- backoff: { type: 'exponential', delay: 1000 },
140
- timeout: 30000, // per-job timeout (ms)
141
- removeOnComplete: true, // or count, or { age, count }
142
- deduplication: { id: 'unique-key', mode: 'simple' },
143
- });
144
-
145
- // Bulk add - 12.7x faster than serial via Batch API
146
- await queue.addBulk([
147
- { name: 'job1', data: { a: 1 } },
148
- { name: 'job2', data: { a: 2 } },
149
- ]);
150
-
151
- await queue.pause();
152
- await queue.resume();
153
- await queue.getJobCounts(); // { waiting, active, delayed, completed, failed }
154
- await queue.obliterate({ force: true });
155
- await queue.close();
156
- ```
157
-
158
- ### Worker
159
-
160
- ```typescript
161
- const worker = new Worker('name', async (job) => {
162
- await job.log('Starting processing');
163
- await job.updateProgress(50);
164
- return result;
165
- }, {
166
- connection,
167
- concurrency: 10,
168
- blockTimeout: 5000,
169
- stalledInterval: 30000,
170
- lockDuration: 30000,
171
- limiter: { max: 100, duration: 60000 },
172
- deadLetterQueue: { name: 'failed-jobs' },
173
- backoffStrategies: {
174
- custom: (attemptsMade, err) => attemptsMade * 1000,
175
- },
176
- });
177
-
178
- worker.on('completed', (job, result) => {});
179
- worker.on('failed', (job, error) => {});
180
- await worker.close();
71
+ worker.on('completed', (job) => console.log(`Job ${job.id} done`));
72
+ worker.on('failed', (job, err) => console.error(`Job ${job.id} failed:`, err.message));
181
73
  ```
182
74
 
183
- ### Flows
75
+ ## Documentation
184
76
 
185
- ```typescript
186
- import { FlowProducer, chain, group, chord } from 'glide-mq';
187
-
188
- // Parent-child
189
- const flow = new FlowProducer({ connection });
190
- await flow.add({
191
- name: 'parent', queueName: 'tasks', data: {},
192
- children: [
193
- { name: 'child1', queueName: 'tasks', data: {} },
194
- { name: 'child2', queueName: 'tasks', data: {} },
195
- ],
196
- });
197
-
198
- // Chain: A -> B -> C (sequential, each step receives previous result)
199
- await chain('tasks', [
200
- { name: 'step1', data: {} },
201
- { name: 'step2', data: {} },
202
- ], connection);
203
-
204
- // Group: A + B + C (parallel, parent completes when all children done)
205
- await group('tasks', [
206
- { name: 'task1', data: {} },
207
- { name: 'task2', data: {} },
208
- ], connection);
209
-
210
- // Chord: run group in parallel, then callback with all results
211
- await chord('tasks', [
212
- { name: 'task1', data: {} },
213
- { name: 'task2', data: {} },
214
- ], { name: 'aggregate', data: {} }, connection);
215
- ```
216
-
217
- ### Events
218
-
219
- ```typescript
220
- import { QueueEvents } from 'glide-mq';
221
-
222
- const events = new QueueEvents('tasks', { connection });
223
- events.on('completed', ({ jobId, returnvalue }) => {});
224
- events.on('failed', ({ jobId, failedReason }) => {});
225
- events.on('stalled', ({ jobId }) => {});
226
- ```
227
-
228
- ### OpenTelemetry
229
-
230
- ```typescript
231
- // Install optional peer dependency
232
- // npm install @opentelemetry/api
233
-
234
- // Automatic tracing for Queue.add and FlowProducer.add
235
- const queue = new Queue('tasks', { connection });
236
- await queue.add('job', data); // Creates span: glide-mq.queue.add
237
-
238
- // Custom tracer (optional)
239
- import { setTracer } from 'glide-mq';
240
- setTracer(customTracerInstance);
241
- ```
242
-
243
- ### Graceful Shutdown
244
-
245
- ```typescript
246
- import { gracefulShutdown } from 'glide-mq';
247
-
248
- const queue = new Queue('tasks', { connection });
249
- const worker = new Worker('tasks', processor, { connection });
250
- const events = new QueueEvents('tasks', { connection });
251
-
252
- // Registers SIGTERM/SIGINT handlers and resolves when all components are closed
253
- await gracefulShutdown([queue, worker, events]);
254
- ```
255
-
256
- ## Cluster Mode
257
-
258
- ```typescript
259
- const connection = {
260
- addresses: [{ host: 'cluster-node', port: 7000 }],
261
- clusterMode: true,
262
- readFrom: ReadFrom.AZAffinity,
263
- clientAz: 'us-east-1a',
264
- };
265
-
266
- // Everything works the same - keys are hash-tagged automatically
267
- const queue = new Queue('tasks', { connection });
268
- ```
269
-
270
- ## Testing Mode
271
-
272
- glide-mq ships a built-in in-memory backend so you can unit-test your job processors **without a running Valkey instance**.
273
-
274
- ```typescript
275
- import { TestQueue, TestWorker } from 'glide-mq/testing';
276
-
277
- const queue = new TestQueue('tasks');
278
-
279
- const worker = new TestWorker(queue, async (job) => {
280
- return { processed: job.data };
281
- });
282
-
283
- worker.on('completed', (job, result) => {
284
- console.log(`Job ${job.id} done:`, result);
285
- });
286
-
287
- worker.on('failed', (job, err) => {
288
- console.error(`Job ${job.id} failed:`, err.message);
289
- });
290
-
291
- await queue.add('send-email', { to: 'user@example.com' });
292
-
293
- // Inspect state without touching Valkey
294
- const counts = await queue.getJobCounts();
295
- // { waiting: 0, active: 0, delayed: 0, completed: 1, failed: 0 }
296
-
297
- // Search jobs by name or data fields
298
- const jobs = await queue.searchJobs({ name: 'send-email', state: 'completed' });
299
-
300
- await worker.close();
301
- await queue.close();
302
- ```
303
-
304
- `TestQueue` and `TestWorker` mirror the real `Queue` / `Worker` public API (add, addBulk, getJob, getJobs, getJobCounts, pause, resume, events, retries, concurrency), making it straightforward to swap implementations between test and production code.
305
-
306
- ## Dashboard
307
-
308
- glide-mq exposes a REST + Server-Sent Events API that can be consumed by the [`@glidemq/dashboard`](https://github.com/avifenesh/glidemq-dashboard) UI package.
309
-
310
- ### Quick start with the built-in demo server
311
-
312
- ```bash
313
- cd demo
314
- npm install
315
- npm run dashboard # starts http://localhost:3000
316
- ```
317
-
318
- ### REST endpoints
319
-
320
- | Method | Path | Description |
321
- |--------|------|-------------|
322
- | `GET` | `/api/queues` | List all queues with counts and metrics |
323
- | `GET` | `/api/queues/:name` | Queue details + recent jobs |
324
- | `GET` | `/api/queues/:name/jobs/:id` | Single job details, state, logs |
325
- | `POST` | `/api/queues/:name/jobs` | Add a new job |
326
- | `POST` | `/api/queues/:name/pause` | Pause a queue |
327
- | `POST` | `/api/queues/:name/resume` | Resume a queue |
328
- | `POST` | `/api/queues/:name/jobs/:id/retry` | Retry a failed job |
329
- | `DELETE` | `/api/queues/:name/jobs/:id` | Remove a job |
330
- | `POST` | `/api/queues/:name/drain` | Drain all waiting jobs |
331
- | `POST` | `/api/queues/:name/obliterate` | Obliterate queue and all data |
332
- | `GET` | `/api/events` | SSE stream for real-time job events |
333
-
334
- ### Real-time events via SSE
335
-
336
- ```javascript
337
- const es = new EventSource('http://localhost:3000/api/events');
338
- es.onmessage = ({ data }) => {
339
- const { queue, event, jobId } = JSON.parse(data);
340
- // event: 'added' | 'completed' | 'failed' | 'progress' | 'stalled' | 'heartbeat'
341
- console.log(`[${queue}] ${event} – job ${jobId}`);
342
- };
343
- ```
344
-
345
- ### Embedding the dashboard server in your own Express app
346
-
347
- ```typescript
348
- import express from 'express';
349
- import { Queue, QueueEvents } from 'glide-mq';
350
-
351
- const app = express();
352
- app.use(express.json());
353
-
354
- const queues: Record<string, Queue> = {
355
- orders: new Queue('orders', { connection }),
356
- payments: new Queue('payments', { connection }),
357
- };
358
-
359
- app.get('/api/queues', async (_req, res) => {
360
- const data = await Promise.all(
361
- Object.entries(queues).map(async ([name, q]) => ({
362
- name,
363
- counts: await q.getJobCounts(),
364
- isPaused: await q.isPaused(),
365
- })),
366
- );
367
- res.json(data);
368
- });
369
- ```
77
+ - **[docs/USAGE.md](docs/USAGE.md)** — Queue & Worker basics, graceful shutdown, cluster mode, event listeners
78
+ - **[docs/ADVANCED.md](docs/ADVANCED.md)** — Schedulers, ordering, deduplication, global concurrency, revocation, compression, retries & DLQ
79
+ - **[docs/WORKFLOWS.md](docs/WORKFLOWS.md)** — FlowProducer, `chain`, `group`, `chord` pipelines
80
+ - **[docs/OBSERVABILITY.md](docs/OBSERVABILITY.md)** — Job logs, metrics, OpenTelemetry, `@glidemq/dashboard`
81
+ - **[docs/TESTING.md](docs/TESTING.md)** `TestQueue` & `TestWorker`, in-memory testing without Valkey
82
+ - **[docs/MIGRATION.md](docs/MIGRATION.md)** — Migrating from BullMQ: API mapping, gaps, and workarounds
370
83
 
371
84
  ## License
372
85
 
@@ -1 +1 @@
1
- {"version":3,"file":"flow-producer.d.ts","sourceRoot":"","sources":["../src/flow-producer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAU,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAM5B,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,GAAG,CAAC;IACT,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;CACtB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,IAAI,CAAsB;IAClC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,OAAO,CAAS;gBAEZ,IAAI,EAAE,mBAAmB;IAIrC,gBAAgB;YACF,SAAS;IAYvB;;;;OAIG;IACG,GAAG,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAe1C;;OAEG;IACG,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IASnD;;;;OAIG;YACW,gBAAgB;IA0I9B;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B"}
1
+ {"version":3,"file":"flow-producer.d.ts","sourceRoot":"","sources":["../src/flow-producer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAU,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAM5B,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,GAAG,CAAC;IACT,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;CACtB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,IAAI,CAAsB;IAClC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,OAAO,CAAS;gBAEZ,IAAI,EAAE,mBAAmB;IAIrC,gBAAgB;YACF,SAAS;IAYvB;;;;OAIG;IACG,GAAG,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAe1C;;OAEG;IACG,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IASnD;;;;OAIG;YACW,gBAAgB;IA2I9B;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B"}
@@ -94,7 +94,7 @@ class FlowProducer {
94
94
  const { addJob } = await Promise.resolve().then(() => __importStar(require('./functions/index')));
95
95
  const timestamp = Date.now();
96
96
  const opts = flow.opts ?? {};
97
- const jobId = await addJob(client, parentKeys, flow.name, JSON.stringify(flow.data), JSON.stringify(opts), timestamp, opts.delay ?? 0, opts.priority ?? 0, '', opts.attempts ?? 0, opts.ordering?.key ?? '');
97
+ const jobId = await addJob(client, parentKeys, flow.name, JSON.stringify(flow.data), JSON.stringify(opts), timestamp, opts.delay ?? 0, opts.priority ?? 0, '', opts.attempts ?? 0, opts.ordering?.key ?? '', opts.ordering?.concurrency ?? 0);
98
98
  const job = new job_1.Job(client, parentKeys, String(jobId), flow.name, flow.data, opts);
99
99
  job.timestamp = timestamp;
100
100
  return { job };
@@ -1 +1 @@
1
- {"version":3,"file":"flow-producer.js","sourceRoot":"","sources":["../src/flow-producer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"flow-producer.js","sourceRoot":"","sources":["../src/flow-producer.ts"],"names":[],"mappings":"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"}