glide-mq 0.8.1 → 0.10.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/CHANGELOG.md +70 -1
- package/README.md +177 -62
- package/dist/base-worker.d.ts +284 -0
- package/dist/base-worker.d.ts.map +1 -0
- package/dist/base-worker.js +1259 -0
- package/dist/base-worker.js.map +1 -0
- package/dist/broadcast-worker.d.ts +36 -0
- package/dist/broadcast-worker.d.ts.map +1 -0
- package/dist/broadcast-worker.js +196 -0
- package/dist/broadcast-worker.js.map +1 -0
- package/dist/broadcast.d.ts +67 -0
- package/dist/broadcast.d.ts.map +1 -0
- package/dist/broadcast.js +109 -0
- package/dist/broadcast.js.map +1 -0
- package/dist/connection.d.ts +5 -1
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +5 -1
- package/dist/connection.js.map +1 -1
- package/dist/dag-utils.d.ts +22 -0
- package/dist/dag-utils.d.ts.map +1 -0
- package/dist/dag-utils.js +170 -0
- package/dist/dag-utils.js.map +1 -0
- package/dist/errors.d.ts +11 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +29 -1
- package/dist/errors.js.map +1 -1
- package/dist/flow-producer.d.ts +11 -1
- package/dist/flow-producer.d.ts.map +1 -1
- package/dist/flow-producer.js +285 -6
- package/dist/flow-producer.js.map +1 -1
- package/dist/functions/index.d.ts +63 -13
- package/dist/functions/index.d.ts.map +1 -1
- package/dist/functions/index.js +1309 -214
- package/dist/functions/index.js.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -1
- package/dist/index.js.map +1 -1
- package/dist/job.d.ts +61 -4
- package/dist/job.d.ts.map +1 -1
- package/dist/job.js +180 -22
- package/dist/job.js.map +1 -1
- package/dist/producer.d.ts +58 -0
- package/dist/producer.d.ts.map +1 -0
- package/dist/producer.js +401 -0
- package/dist/producer.js.map +1 -0
- package/dist/proxy/index.d.ts +30 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/index.js +61 -0
- package/dist/proxy/index.js.map +1 -0
- package/dist/proxy/routes.d.ts +13 -0
- package/dist/proxy/routes.d.ts.map +1 -0
- package/dist/proxy/routes.js +327 -0
- package/dist/proxy/routes.js.map +1 -0
- package/dist/proxy/types.d.ts +102 -0
- package/dist/proxy/types.d.ts.map +1 -0
- package/dist/proxy/types.js +3 -0
- package/dist/proxy/types.js.map +1 -0
- package/dist/queue-events.d.ts.map +1 -1
- package/dist/queue-events.js +25 -15
- package/dist/queue-events.js.map +1 -1
- package/dist/queue.d.ts +23 -6
- package/dist/queue.d.ts.map +1 -1
- package/dist/queue.js +586 -70
- package/dist/queue.js.map +1 -1
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +10 -3
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/pool.d.ts.map +1 -1
- package/dist/sandbox/pool.js +29 -1
- package/dist/sandbox/pool.js.map +1 -1
- package/dist/sandbox/runner.js +5 -1
- package/dist/sandbox/runner.js.map +1 -1
- package/dist/sandbox/sandbox-job.d.ts +2 -0
- package/dist/sandbox/sandbox-job.d.ts.map +1 -1
- package/dist/sandbox/sandbox-job.js +21 -0
- package/dist/sandbox/sandbox-job.js.map +1 -1
- package/dist/sandbox/types.d.ts +2 -1
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/scheduler.d.ts +32 -1
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +275 -65
- package/dist/scheduler.js.map +1 -1
- package/dist/serverless-pool.d.ts +30 -0
- package/dist/serverless-pool.d.ts.map +1 -0
- package/dist/serverless-pool.js +75 -0
- package/dist/serverless-pool.js.map +1 -0
- package/dist/testing.d.ts +59 -5
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +559 -29
- package/dist/testing.js.map +1 -1
- package/dist/types.d.ts +179 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +63 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +492 -25
- package/dist/utils.js.map +1 -1
- package/dist/worker.d.ts +13 -151
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +137 -736
- package/dist/worker.js.map +1 -1
- package/dist/workflows.d.ts +20 -1
- package/dist/workflows.d.ts.map +1 -1
- package/dist/workflows.js +30 -0
- package/dist/workflows.js.map +1 -1
- package/package.json +11 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,7 +6,76 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
## [
|
|
9
|
+
## [0.10.0] - 2026-03-09
|
|
10
|
+
|
|
11
|
+
### Performance
|
|
12
|
+
|
|
13
|
+
- **~108% throughput improvement at c=1** (~1,300 -> ~2,700 jobs/s) by eliminating wasted HMGET round-trip in `buildParentInfo` for non-parent jobs (#126).
|
|
14
|
+
- **~9-16% throughput improvement at c=10** (~12,900 -> ~14,000-15,000 jobs/s) via combined hot-path optimizations (#126).
|
|
15
|
+
- New `glidemq_popLists` server function: checks priority + LIFO lists in a single FCALL instead of 2 separate RPOPs.
|
|
16
|
+
- `completeAndFetchNext` Lua fast-path hints: `processedOn` timestamp passed from TS (skip HGET), `'__'` sentinels for ordering/group keys (skip entire Lua call when confirmed absent), `hasParents` flag (skip SMEMBERS for non-DAG jobs).
|
|
17
|
+
- `Date.now()` cached once per job completion, shared across completeAndFetchNext, finishedOn, and scheduler callbacks.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- Worker options `events: false` / `metrics: false` to skip XADD event stream writes and HINCRBY metrics recording in Lua on the hot path. TS-side EventEmitter (`'completed'`, `'failed'`, etc.) is unaffected. Reduces Valkey memory and CPU for high-throughput deployments that don't consume server-side events or metrics (#126).
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Ordering key `'__'` is now rejected as reserved (internal sentinel collision guard).
|
|
26
|
+
- `hasParents` flag narrowed to DAG-only `parentIds` - saves one SMEMBERS call for single-parent flow jobs.
|
|
27
|
+
- Version changelog comments in Lua library corrected (v59-v64 entries).
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- Function library version bumped from 60 to 64 (auto-upgrades on connection).
|
|
32
|
+
- Benchmark durations increased (ADD_DURATION 5s->15s, PROCESS_SIZES [500,2000]->[5000,20000]) for more stable measurements.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## [0.9.0] - 2026-03-08
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- Subject-based filtering for `BroadcastWorker` - NATS-style wildcard matching on job names. Configure via `subjects` option with `*` (single-token) and `>` (multi-token) wildcards. Non-matching messages are auto-acknowledged. Exported `matchSubject` and `compileSubjectMatcher` utilities (#119).
|
|
41
|
+
- `Producer` class - lightweight job enqueuing for serverless/edge environments without EventEmitter or Job instances. Returns plain string IDs. Use with `ServerlessPool` for automatic connection reuse across warm Lambda/Edge invocations. API: `add(name, data, opts)`, `addBulk(jobs)`, `close()` (#112).
|
|
42
|
+
- `ServerlessPool` and `serverlessPool` singleton - connection pooling for serverless environments. Caches Producer instances by queue name and connection fingerprint. API: `getProducer(name, opts)`, `closeAll()`, `size` (#112).
|
|
43
|
+
- LIFO (Last-In-First-Out) job processing via `lifo: true` option. Uses dedicated Valkey LIST with RPUSH/RPOP. Priority and delayed jobs take precedence. Cannot be combined with ordering keys (#87).
|
|
44
|
+
- Time-series metrics - `queue.getMetrics(type, opts?)` returns per-minute throughput and latency data with 24-hour retention. Zero extra RTTs (#82).
|
|
45
|
+
- `opts.jobId` - custom job IDs for deterministic identity. Max 256 characters (#79).
|
|
46
|
+
- `queue.addAndWait(name, data, { waitTimeout })` - enqueue and wait for completion without polling.
|
|
47
|
+
- `job.moveToDelayed(timestampMs, nextStep?)` - pause active job mid-processor for step-job workflows.
|
|
48
|
+
- `DelayedError` - exported error type for step-job control.
|
|
49
|
+
- Batch processing via `batch: { size, timeout? }` option. Processor receives `Job[]`, returns `R[]`. `BatchError` for partial failure (#81).
|
|
50
|
+
- `glide-mq/proxy` subpath - HTTP proxy for cross-language job enqueue. REST endpoints with queue allowlist, 1MB limit, graceful shutdown (#83).
|
|
51
|
+
- Wire protocol documentation (`docs/WIRE_PROTOCOL.md`) - raw FCALL reference for any language (#83).
|
|
52
|
+
- DAG workflows - `FlowProducer.addDAG()` and `dag()` helper for arbitrary DAG topologies (#86).
|
|
53
|
+
- Serverless usage guide (`docs/SERVERLESS.md`) - Lambda, Cloudflare Workers, Vercel Edge examples.
|
|
54
|
+
- List-active counter self-healing via `glidemq_healListActive` Lua function. Automatically corrects counter drift caused by worker crashes during scheduler promotion ticks (#124).
|
|
55
|
+
- Proxy endpoints: `GET /queues/:name/jobs` (list/filter), `DELETE /queues/:name/jobs/:id` (#124).
|
|
56
|
+
- CI: `npm audit` security scanning, `timeout-minutes` on all jobs, `npm ci` with cache in publish workflow (#124).
|
|
57
|
+
|
|
58
|
+
### Fixed
|
|
59
|
+
|
|
60
|
+
- 62 issues from deep project audit across 7 domains (security, performance, code quality, architecture, testing, backend, devops) (#124):
|
|
61
|
+
- **Critical**: Worker heartbeat unhandled rejections, proxy validation gaps (NaN/Infinity), proxy queue cache race condition, poll loop promise handling on close, cross-queue parent registration error handling.
|
|
62
|
+
- **Security**: Sandbox path traversal protection via `realpathSync`, proxy input validation with `Number.isFinite`, queue name length limit (256 chars).
|
|
63
|
+
- **Performance**: Lua metrics HKEYS scan frequency reduced 10x, token bucket early exit, DAG string parsing O(n) to O(1).
|
|
64
|
+
- **Reliability**: Worker/Producer `close()` with double-close guard and closed flag, `QueueEvents` recursive poll guard, sandbox pool exit/error listener cleanup, serverless pool closing state guard.
|
|
65
|
+
- **Proxy**: Configurable `onError` callback (replaces silent error swallowing), graceful shutdown with draining flag, pause/resume returns 200 with state.
|
|
66
|
+
- `globalConcurrency` enforced for LIFO/priority-list jobs via atomic `rpopAndReserve` (#87).
|
|
67
|
+
- Scheduler LIFO forwarding and FlowProducer child LIFO routing (#87).
|
|
68
|
+
- `list-active` counter DECR on job removal/deferral (#87).
|
|
69
|
+
- Function library bumped to version 60.
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
|
|
73
|
+
- **Breaking (internal)**: `Worker` and `BroadcastWorker` now extend `BaseWorker` abstract class. Public API unchanged. Eliminates ~1400 lines of duplication (3407 to 2024 lines, 41% reduction) (#124).
|
|
74
|
+
- Worker uses explicit state machine (7 states: created, initializing, running, paused, draining, closing, closed) replacing boolean flags (#124).
|
|
75
|
+
- Proxy pause/resume endpoints return 200 with `{ paused: boolean }` instead of 204 (#124).
|
|
76
|
+
- Proxy health endpoint includes `queues` count (#124).
|
|
77
|
+
- Test suite: 24 hardcoded `setTimeout` waits replaced with `waitFor` predicates (#124).
|
|
78
|
+
- 79 eslint `no-unused-vars` warnings resolved across test files (#124).
|
|
10
79
|
|
|
11
80
|
---
|
|
12
81
|
|
package/README.md
CHANGED
|
@@ -1,56 +1,42 @@
|
|
|
1
1
|
# glide-mq
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/glide-mq)
|
|
4
|
+
[](https://github.com/avifenesh/glide-mq/blob/main/LICENSE)
|
|
5
|
+
[](https://github.com/avifenesh/glide-mq/actions/workflows/ci.yml)
|
|
6
|
+
[](https://nodejs.org/)
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
High-performance message queue for Node.js built on Valkey/Redis Streams with 1-RTT job operations and cluster-native design.
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
npm install glide-mq
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Why glide-mq
|
|
10
|
+
glide-mq is for anyone building background jobs, task queues, or workflow orchestration in Node.js. It connects through a Rust-native NAPI client ([valkey-glide](https://github.com/valkey-io/valkey-glide)), executes all queue logic in a single Valkey Server Function call per operation (FCALL, not EVAL), and hash-tags every key for automatic cluster slot alignment. The result is fewer round trips, no Lua cache misses, and zero cluster configuration.
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
- **Rust core, not ioredis** — built on [Valkey GLIDE](https://github.com/valkey-io/valkey-glide)'s native NAPI bindings for lower latency and less GC pressure
|
|
15
|
-
- **1 function library, not 53 scripts** — all queue logic runs as a single Valkey Server Function (no EVAL overhead)
|
|
16
|
-
- **Cluster-native** — hash-tagged keys work out of the box; no manual `{braces}` needed
|
|
17
|
-
- **Cloud-ready** — AZ-affinity routing and IAM auth built in
|
|
12
|
+
> If glide-mq is useful to you, consider giving it a star on [GitHub](https://github.com/avifenesh/glide-mq). It helps others discover the project.
|
|
18
13
|
|
|
19
|
-
##
|
|
14
|
+
## Why glide-mq
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
16
|
+
- Use this when you need **throughput**: 48k jobs/s at concurrency=50, 4x faster than BullMQ on the same hardware.
|
|
17
|
+
- Use this when you run **Valkey/Redis clusters**: all keys hash-tagged out of the box, no `{braces}` workarounds.
|
|
18
|
+
- Use this when you need **workflows**: parent-child trees, DAGs with fan-in, step jobs, batch processing, and cron scheduling in one library.
|
|
19
|
+
- Use this when you deploy to **serverless**: lightweight `Producer` and `ServerlessPool` cache connections across warm invocations.
|
|
20
|
+
- Use this when you want **pub/sub with durability**: `Broadcast` delivers to all subscribers with retries, backpressure, and NATS-style subject filtering.
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
- **Retries, backoff, and DLQ** — exponential/fixed/custom retries with dead-letter queues ([Advanced](docs/ADVANCED.md#retries-and-backoff), [Demo](demo/README.md#demo-scenarios))
|
|
28
|
-
- **Stalled recovery, pause/resume, and drain** — auto-reclaim stuck jobs, pause processing, and server-side drain waiting/delayed jobs ([Usage](docs/USAGE.md#worker), [Demo](demo/README.md#api-endpoints-dashboard-server))
|
|
29
|
-
- **Job revocation + sandboxed processors** — cooperative cancellation and isolated file-based processors in worker threads/child processes ([Advanced](docs/ADVANCED.md#job-revocation), [Architecture](docs/ARCHITECTURE.md#typescript-api), [Sandbox example](tests/sandbox-integration.test.ts))
|
|
22
|
+
## Install
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
- **Per-key ordering, global concurrency, and rate limiting** — deterministic ordering with queue-wide and token-bucket controls ([Advanced](docs/ADVANCED.md#ordering-and-group-concurrency), [Advanced](docs/ADVANCED.md#global-concurrency), [Advanced](docs/ADVANCED.md#global-rate-limiting))
|
|
35
|
-
- **Deduplication** — simple, throttle, and debounce modes with TTL ([Advanced](docs/ADVANCED.md#deduplication), [Demo](demo/README.md#demo-scenarios))
|
|
24
|
+
```bash
|
|
25
|
+
npm install glide-mq
|
|
26
|
+
```
|
|
36
27
|
|
|
37
|
-
|
|
38
|
-
- **QueueEvents, metrics, logs, and dashboard** — real-time events + OpenTelemetry + [`@glidemq/dashboard`](https://github.com/avifenesh/glidemq-dashboard) ([Observability](docs/OBSERVABILITY.md), [Dashboard demo API](demo/dashboard-server.ts))
|
|
39
|
-
- **Compression, graceful shutdown, and shared connections** — lower payload size and easier process lifecycle management ([Advanced](docs/ADVANCED.md#transparent-compression), [Usage](docs/USAGE.md#graceful-shutdown), [Advanced](docs/ADVANCED.md#shared-client))
|
|
40
|
-
- **In-memory testing mode** — `TestQueue` and `TestWorker` with zero Valkey dependency ([Testing](docs/TESTING.md), [Testing-mode test](tests/testing-mode.test.ts))
|
|
28
|
+
Requires Node.js 20+ and a running [Valkey](https://valkey.io) 7.0+ or Redis 7.0+ instance.
|
|
41
29
|
|
|
42
|
-
## Quick
|
|
30
|
+
## Quick start
|
|
43
31
|
|
|
44
32
|
```typescript
|
|
45
33
|
import { Queue, Worker } from 'glide-mq';
|
|
46
34
|
|
|
47
35
|
const connection = { addresses: [{ host: 'localhost', port: 6379 }] };
|
|
48
36
|
|
|
49
|
-
// Producer
|
|
50
37
|
const queue = new Queue('tasks', { connection });
|
|
51
38
|
await queue.add('send-email', { to: 'user@example.com', subject: 'Hello' });
|
|
52
39
|
|
|
53
|
-
// Consumer
|
|
54
40
|
const worker = new Worker('tasks', async (job) => {
|
|
55
41
|
console.log(`Processing ${job.name}:`, job.data);
|
|
56
42
|
return { sent: true };
|
|
@@ -60,8 +46,6 @@ worker.on('completed', (job) => console.log(`Job ${job.id} done`));
|
|
|
60
46
|
worker.on('failed', (job, err) => console.error(`Job ${job.id} failed:`, err.message));
|
|
61
47
|
```
|
|
62
48
|
|
|
63
|
-
Requires Node.js 20+ and a running [Valkey](https://valkey.io) (7.0+) or Redis 7.0+ instance.
|
|
64
|
-
|
|
65
49
|
## Benchmarks
|
|
66
50
|
|
|
67
51
|
| Concurrency | Throughput |
|
|
@@ -71,47 +55,178 @@ Requires Node.js 20+ and a running [Valkey](https://valkey.io) (7.0+) or Redis 7
|
|
|
71
55
|
| c=10 | 15,504 jobs/s |
|
|
72
56
|
| c=50 | 48,077 jobs/s |
|
|
73
57
|
|
|
74
|
-
`addBulk` batch API: **1,000 jobs in 18 ms** (12.
|
|
58
|
+
`addBulk` batch API: **1,000 jobs in 18 ms** (12.7x faster than serial).
|
|
75
59
|
Gzip compression: **98% payload reduction** on 15 KB payloads.
|
|
76
60
|
|
|
77
61
|
*Valkey 8.0, single node, no-op processor. Run `npm run bench` to reproduce.*
|
|
78
62
|
|
|
79
|
-
##
|
|
63
|
+
## Comparison
|
|
64
|
+
|
|
65
|
+
| | glide-mq | BullMQ | Bee Queue |
|
|
66
|
+
|---|---|---|---|
|
|
67
|
+
| **Network per job** | 1 RTT (`completeAndFetchNext`) | 4-7 RTTs (lock + complete + fetch) | 2-3 RTTs |
|
|
68
|
+
| **Client** | Rust NAPI ([valkey-glide](https://github.com/valkey-io/valkey-glide)) | ioredis (pure JS) | node_redis (pure JS) |
|
|
69
|
+
| **Server logic** | 1 Valkey Function library (persistent, named) | 53 EVAL scripts (cache-miss prone) | Lua scripts |
|
|
70
|
+
| **Cluster** | Hash-tagged keys, zero config | Manual `{braces}` or workarounds | Not supported |
|
|
71
|
+
| **Workflows** | FlowProducer trees, DAG, chain/group/chord | FlowProducer trees | Not supported |
|
|
72
|
+
| **Pub/sub** | Native Broadcast with subject filtering | Not supported | Not supported |
|
|
73
|
+
| **Serverless** | Producer + ServerlessPool | Not supported | Not supported |
|
|
74
|
+
| **Throughput** | 48k jobs/s (c=50) | ~12k jobs/s (c=50) | ~5k jobs/s (c=50) |
|
|
75
|
+
|
|
76
|
+
## Core concepts
|
|
77
|
+
|
|
78
|
+
- **Queue** -- stores jobs in Valkey Streams. Handles enqueue, delay, priority, pause, drain, and bulk operations.
|
|
79
|
+
- **Worker** -- processes jobs with configurable concurrency, prefetch, lock duration, and stalled-job recovery.
|
|
80
|
+
- **Job** -- a unit of work with name, data, options (retries, backoff, priority, TTL), and lifecycle events.
|
|
81
|
+
- **FlowProducer** -- creates parent-child job trees and DAGs. A parent waits for all children before processing.
|
|
82
|
+
- **Producer** -- lightweight enqueue-only client. No EventEmitter, no Job instances, returns plain string IDs. Built for serverless.
|
|
83
|
+
- **Broadcast** -- fan-out pub/sub. Each message is delivered to every subscriber group with independent retries and backpressure.
|
|
84
|
+
- **QueueEvents** -- real-time stream of job lifecycle events (completed, failed, delayed, waiting, etc.).
|
|
80
85
|
|
|
81
|
-
|
|
86
|
+
## Features
|
|
82
87
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
### Core
|
|
89
|
+
|
|
90
|
+
- **Queues and workers** with configurable concurrency, prefetch, and lock duration ([Usage](docs/USAGE.md))
|
|
91
|
+
- **Delayed, priority, and bulk enqueue** for scheduling and high-throughput ingestion ([Usage](docs/USAGE.md))
|
|
92
|
+
- **Batch processing** -- process multiple jobs at once via `batch: { size, timeout? }` ([Usage](docs/USAGE.md#batch-processing))
|
|
93
|
+
- **Request-reply** -- `queue.addAndWait(name, data, { waitTimeout })` for synchronous RPC ([Usage](docs/USAGE.md#request-reply-with-addandwait))
|
|
94
|
+
- **LIFO mode** -- `lifo: true` processes newest jobs first ([Advanced](docs/ADVANCED.md#lifo-mode))
|
|
95
|
+
- **Job TTL** -- auto-expire jobs after a time-to-live window ([Advanced](docs/ADVANCED.md#job-ttl))
|
|
96
|
+
- **Custom job IDs** -- deterministic, idempotent enqueue; duplicates return `null` ([Advanced](docs/ADVANCED.md#custom-job-ids))
|
|
97
|
+
- **Pluggable serializers** -- swap JSON for any `{ serialize, deserialize }` implementation ([Advanced](docs/ADVANCED.md#pluggable-serializers))
|
|
98
|
+
- **Transparent compression** -- gzip payloads at the queue level ([Advanced](docs/ADVANCED.md#transparent-compression))
|
|
99
|
+
|
|
100
|
+
### Reliability
|
|
101
|
+
|
|
102
|
+
- **Retries with exponential, fixed, or custom backoff** and dead-letter queues ([Advanced](docs/ADVANCED.md#retries-and-backoff))
|
|
103
|
+
- **UnrecoverableError** -- skip all retries and fail permanently ([Usage](docs/USAGE.md#unrecoverableerror))
|
|
104
|
+
- **Stalled recovery** -- auto-reclaim stuck jobs via consumer group PEL and `XAUTOCLAIM` ([Usage](docs/USAGE.md#worker))
|
|
105
|
+
- **Job revocation** -- cooperative cancellation with `AbortSignal` ([Advanced](docs/ADVANCED.md#job-revocation))
|
|
106
|
+
- **Deduplication** -- simple, throttle, and debounce modes with configurable TTL ([Advanced](docs/ADVANCED.md#deduplication))
|
|
107
|
+
- **Per-key ordering** -- sequential processing per ordering key with configurable group concurrency ([Advanced](docs/ADVANCED.md#ordering-and-group-concurrency))
|
|
108
|
+
- **Rate limiting** -- per-group sliding window, token bucket, and global queue-wide limits ([Advanced](docs/ADVANCED.md#global-rate-limiting))
|
|
109
|
+
- **Sandboxed processors** -- run processors in worker threads or child processes ([Architecture](docs/ARCHITECTURE.md))
|
|
110
|
+
|
|
111
|
+
### Orchestration
|
|
112
|
+
|
|
113
|
+
- **FlowProducer** -- parent-child job trees with `chain`, `group`, and `chord` helpers ([Workflows](docs/WORKFLOWS.md))
|
|
114
|
+
- **DAG workflows** -- arbitrary dependency graphs with `FlowProducer.addDAG()` and `dag()` helper; multi-parent fan-in, diamond patterns, cycle detection ([Workflows](docs/WORKFLOWS.md))
|
|
115
|
+
- **Step jobs** -- `job.moveToDelayed(timestamp, nextStep)` suspends a job mid-processor and resumes later ([Usage](docs/USAGE.md#pause-and-resume-a-job-later-step-jobs))
|
|
116
|
+
- **Dynamic children** -- `job.moveToWaitingChildren()` pauses a parent to add children mid-execution ([Workflows](docs/WORKFLOWS.md))
|
|
117
|
+
- **Batch processing** -- process multiple jobs at once for bulk I/O ([Usage](docs/USAGE.md#batch-processing))
|
|
118
|
+
|
|
119
|
+
### Scheduling
|
|
120
|
+
|
|
121
|
+
- **Cron and interval schedulers** -- 5-field cron with timezone, fixed intervals, and `repeatAfterComplete` mode ([Advanced](docs/ADVANCED.md#job-schedulers))
|
|
122
|
+
- **Bounded schedulers** -- `limit`, `startDate`, and `endDate` for finite schedules ([Advanced](docs/ADVANCED.md#bounded-schedulers))
|
|
123
|
+
|
|
124
|
+
### Pub/Sub
|
|
125
|
+
|
|
126
|
+
- **Broadcast** -- fan-out delivery to all subscriber groups ([Usage](docs/USAGE.md#broadcast--broadcastworker))
|
|
127
|
+
- **BroadcastWorker** -- independent consumer groups with own retries, concurrency, and backpressure ([Usage](docs/USAGE.md#broadcast--broadcastworker))
|
|
128
|
+
- **Subject filtering** -- NATS-style patterns (`*` one segment, `>` trailing wildcard) for topic-based routing ([Usage](docs/USAGE.md#broadcast--broadcastworker))
|
|
129
|
+
|
|
130
|
+
### Serverless
|
|
131
|
+
|
|
132
|
+
- **Producer** -- enqueue without EventEmitter overhead, returns plain string IDs ([Usage](docs/USAGE.md))
|
|
133
|
+
- **ServerlessPool** -- connection caching across warm Lambda/Edge invocations ([Serverless](docs/SERVERLESS.md))
|
|
134
|
+
|
|
135
|
+
### Observability
|
|
136
|
+
|
|
137
|
+
- **QueueEvents** -- real-time stream-based lifecycle events ([Observability](docs/OBSERVABILITY.md))
|
|
138
|
+
- **Time-series metrics** -- per-minute throughput and latency retained 24h, recorded server-side ([Observability](docs/OBSERVABILITY.md))
|
|
139
|
+
- **OpenTelemetry** -- automatic span emission; bring your own tracer or auto-detect `@opentelemetry/api` ([Observability](docs/OBSERVABILITY.md))
|
|
140
|
+
- **Job logs** -- append structured log entries per job with pagination ([Observability](docs/OBSERVABILITY.md))
|
|
141
|
+
- **Job mutations** -- `changePriority()`, `changeDelay()`, `promote()` after enqueue; `retryJobs()` and `clean()` in bulk ([Usage](docs/USAGE.md))
|
|
142
|
+
- **Graceful shutdown** -- `gracefulShutdown()` helper registers SIGTERM/SIGINT handlers ([Usage](docs/USAGE.md#graceful-shutdown))
|
|
143
|
+
- **In-memory testing** -- `TestQueue` and `TestWorker` with zero Valkey dependency ([Testing](docs/TESTING.md))
|
|
144
|
+
|
|
145
|
+
### Cloud
|
|
146
|
+
|
|
147
|
+
- **Cluster-native** -- hash-tagged keys `glide:{queueName}:*` route all queue data to the same slot ([Usage](docs/USAGE.md#cluster-mode))
|
|
148
|
+
- **IAM authentication** -- native SigV4 auth for AWS ElastiCache and MemoryDB ([Usage](docs/USAGE.md#cluster-mode))
|
|
149
|
+
- **AZ-affinity routing** -- `readFrom: 'AZAffinity'` routes reads to same-AZ replicas ([Usage](docs/USAGE.md#cluster-mode))
|
|
150
|
+
|
|
151
|
+
## Framework integrations
|
|
152
|
+
|
|
153
|
+
| Package | Install | Setup |
|
|
154
|
+
|---------|---------|-------|
|
|
155
|
+
| [`@glidemq/hono`](https://github.com/avifenesh/glidemq-hono) | `npm i @glidemq/hono` | `app.use(glideMQ({ connection, queues: { ... } }))` |
|
|
156
|
+
| [`@glidemq/fastify`](https://github.com/avifenesh/glidemq-fastify) | `npm i @glidemq/fastify` | `app.register(glideMQPlugin, { connection, queues: { ... } })` |
|
|
157
|
+
| [`@glidemq/nestjs`](https://github.com/avifenesh/glidemq-nestjs) | `npm i @glidemq/nestjs` | `GlideMQModule.forRoot({ connection, queues: { ... } })` |
|
|
158
|
+
| [`@glidemq/dashboard`](https://github.com/avifenesh/glidemq-dashboard) | `npm i @glidemq/dashboard` | `app.use('/dashboard', createDashboard([queue1, queue2]))` |
|
|
159
|
+
| @glidemq/hapi | coming soon | Hapi plugin with the same REST + SSE surface |
|
|
160
|
+
|
|
161
|
+
All framework packages provide REST endpoints, SSE events, and serverless Producer support. See each package's README for full documentation.
|
|
162
|
+
|
|
163
|
+
## Cross-language
|
|
164
|
+
|
|
165
|
+
Non-Node.js services can enqueue jobs into glide-mq queues using the HTTP proxy or direct FCALL:
|
|
86
166
|
|
|
87
167
|
```typescript
|
|
88
|
-
import {
|
|
168
|
+
import { createProxyServer } from 'glide-mq/proxy';
|
|
89
169
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
})
|
|
170
|
+
const proxy = createProxyServer({
|
|
171
|
+
connection: { addresses: [{ host: 'localhost', port: 6379 }] },
|
|
172
|
+
queues: ['emails', 'reports'],
|
|
173
|
+
});
|
|
174
|
+
proxy.app.listen(3000);
|
|
94
175
|
```
|
|
95
176
|
|
|
96
|
-
|
|
177
|
+
```bash
|
|
178
|
+
curl -X POST http://localhost:3000/queues/emails/jobs \
|
|
179
|
+
-H 'Content-Type: application/json' \
|
|
180
|
+
-d '{"name": "send-email", "data": {"to": "user@example.com"}}'
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Endpoints: `POST /queues/:name/jobs`, `POST /queues/:name/jobs/bulk`, `GET /queues/:name/jobs/:id`, `POST /queues/:name/pause`, `POST /queues/:name/resume`, `GET /queues/:name/counts`, `GET /health`.
|
|
184
|
+
|
|
185
|
+
For zero-overhead integration, call Valkey Server Functions directly from any language with a Valkey client. See [Wire Protocol](docs/WIRE_PROTOCOL.md) for FCALL signatures, key layout, and examples in Python and Go.
|
|
97
186
|
|
|
98
187
|
## Documentation
|
|
99
188
|
|
|
100
|
-
| Guide |
|
|
101
|
-
|
|
102
|
-
| [Usage](docs/USAGE.md) | Queue
|
|
103
|
-
| [Advanced](docs/ADVANCED.md) | Schedulers, rate limiting, dedup, compression, retries
|
|
104
|
-
| [Workflows](docs/WORKFLOWS.md) | FlowProducer, `chain`, `group`, `chord
|
|
105
|
-
| [Observability](docs/OBSERVABILITY.md) | OpenTelemetry, job logs,
|
|
106
|
-
| [
|
|
107
|
-
| [
|
|
108
|
-
| [
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
189
|
+
| Guide | Topics |
|
|
190
|
+
|-------|--------|
|
|
191
|
+
| [Usage](docs/USAGE.md) | Queue, Worker, Broadcast, Producer, batch, request-reply, step jobs, graceful shutdown, cluster mode |
|
|
192
|
+
| [Advanced](docs/ADVANCED.md) | Schedulers, rate limiting, dedup, compression, retries, DLQ, custom IDs, LIFO, TTL, serializers |
|
|
193
|
+
| [Workflows](docs/WORKFLOWS.md) | FlowProducer, DAG, `chain`, `group`, `chord`, dynamic children |
|
|
194
|
+
| [Observability](docs/OBSERVABILITY.md) | OpenTelemetry, time-series metrics, job logs, dashboard |
|
|
195
|
+
| [Serverless](docs/SERVERLESS.md) | Producer, ServerlessPool, Lambda and Edge deployment |
|
|
196
|
+
| [Testing](docs/TESTING.md) | In-memory `TestQueue` and `TestWorker` -- no Valkey needed |
|
|
197
|
+
| [Wire Protocol](docs/WIRE_PROTOCOL.md) | Cross-language FCALL specs, key layout, Python and Go examples |
|
|
198
|
+
| [Architecture](docs/ARCHITECTURE.md) | Key design, Valkey functions, LIFO, Broadcast, DAG internals |
|
|
199
|
+
| [Durability](docs/DURABILITY.md) | Persistence modes, crash windows, feature-specific durability |
|
|
200
|
+
| [Migration](docs/MIGRATION.md) | Coming from BullMQ? API mapping and step-by-step guide |
|
|
201
|
+
|
|
202
|
+
## Limitations
|
|
203
|
+
|
|
204
|
+
- Requires a running Valkey 7.0+ or Redis 7.0+ instance. There is no embedded mode.
|
|
205
|
+
- Node.js only. The Rust-native NAPI client (`@valkey/valkey-glide`) does not run in browsers or Deno.
|
|
206
|
+
- At-least-once delivery semantics. Jobs may be processed more than once after crashes or stalled recovery.
|
|
207
|
+
- Not a streaming platform. glide-mq is a job/task queue, not a replacement for Kafka or NATS JetStream.
|
|
208
|
+
- Single dependency on `@glidemq/speedkey` (which wraps `@valkey/valkey-glide`). Native addon compilation is required on install.
|
|
209
|
+
|
|
210
|
+
## Ecosystem
|
|
211
|
+
|
|
212
|
+
| Package | Description | Links |
|
|
213
|
+
|---------|-------------|-------|
|
|
214
|
+
| [glide-mq](https://github.com/avifenesh/glide-mq) | Core queue library | [npm](https://www.npmjs.com/package/glide-mq) |
|
|
215
|
+
| [@glidemq/hono](https://github.com/avifenesh/glidemq-hono) | Hono middleware -- REST endpoints, SSE, serverless Producer | [npm](https://www.npmjs.com/package/@glidemq/hono) |
|
|
216
|
+
| [@glidemq/fastify](https://github.com/avifenesh/glidemq-fastify) | Fastify plugin -- REST endpoints, SSE, serverless Producer | [npm](https://www.npmjs.com/package/@glidemq/fastify) |
|
|
217
|
+
| [@glidemq/nestjs](https://github.com/avifenesh/glidemq-nestjs) | NestJS module -- decorators, DI, lifecycle management | [npm](https://www.npmjs.com/package/@glidemq/nestjs) |
|
|
218
|
+
| [@glidemq/dashboard](https://github.com/avifenesh/glidemq-dashboard) | Web UI -- metrics charts, scheduler management, job mutations | [npm](https://www.npmjs.com/package/@glidemq/dashboard) |
|
|
219
|
+
| [@glidemq/speedkey](https://github.com/avifenesh/speedkey) | Valkey GLIDE client with native NAPI bindings | [npm](https://www.npmjs.com/package/@glidemq/speedkey) |
|
|
220
|
+
| [glidemq-examples](https://github.com/avifenesh/glidemq-examples) | 34 runnable examples across frameworks and use cases | [GitHub](https://github.com/avifenesh/glidemq-examples) |
|
|
221
|
+
|
|
222
|
+
> If glide-mq is useful to you, consider [starring the repo](https://github.com/avifenesh/glide-mq). It helps others find the project.
|
|
223
|
+
|
|
224
|
+
## Contributing
|
|
225
|
+
|
|
226
|
+
Bug reports, feature requests, and pull requests are welcome. See [CHANGELOG.md](CHANGELOG.md) for release history.
|
|
227
|
+
|
|
228
|
+
- [Open an issue](https://github.com/avifenesh/glide-mq/issues)
|
|
229
|
+
- [Discussions](https://github.com/avifenesh/glide-mq/discussions)
|
|
115
230
|
|
|
116
231
|
## License
|
|
117
232
|
|