power-queues 2.0.12 → 2.0.13
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/README.md +127 -117
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,146 +1,156 @@
|
|
|
1
1
|
# power-queues
|
|
2
|
-
|
|
2
|
+
## High-Performance Redis Streams Queue for Node.js
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
Ultra-fast, fault-tolerant, Lua-optimized distributed task queue built on Redis Streams.
|
|
5
|
+
Supports **bulk XADD**, **idempotent jobs**, **retries**, **DLQ**, **stuck-task recovery**, **batching**, and **consumer groups**.
|
|
6
|
+
Designed for large-scale microservices, telemetry pipelines, and high-load systems.
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
|
|
8
|
+
<p align="center">
|
|
9
|
+
<img src="https://img.shields.io/badge/redis-streams-red?logo=redis" />
|
|
10
|
+
<img src="https://img.shields.io/badge/nodejs-queue-green?logo=node.js" />
|
|
11
|
+
<img src="https://img.shields.io/badge/typescript-ready-blue?logo=typescript" />
|
|
12
|
+
<img src="https://img.shields.io/badge/nestjs-support-ea2845?logo=nestjs" />
|
|
13
|
+
<img src="https://img.shields.io/badge/license-MIT-lightgrey" />
|
|
14
|
+
<img src="https://img.shields.io/badge/status-production-success" />
|
|
15
|
+
</p>
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
---
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
> Uses utilities from [**full-utils**](https://github.com/ihor-bielchenko/full-utils)
|
|
19
|
+
## 📚 Documentation
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
Full documentation is available here:
|
|
22
|
+
👉 **https://power-queues.docs.ihor.bielchenko.com**
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
---
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
custom Redis-based queues with full control over task lifecycle and execution flow.
|
|
26
|
+
## 🚀 Features
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
- ⚡ **Bulk XADD** — send thousands of tasks in a single Redis call
|
|
29
|
+
- 🔁 **Retries & attempt tracking**
|
|
30
|
+
- 🧠 **Idempotent job execution** (Lua locks, TTL, start/done keys)
|
|
31
|
+
- 🧹 **Stuck task recovery** (XAUTOCLAIM + Lua-based recovery)
|
|
32
|
+
- 🌀 **Consumer groups + batching**
|
|
33
|
+
- 📥 **Dead Letter Queue (DLQ)**
|
|
34
|
+
- 🔐 **Stream trimming, approx/exact maxlen, minid window**
|
|
35
|
+
- 🧱 **Fully async, high-throughput, production-ready**
|
|
27
36
|
|
|
28
|
-
|
|
29
|
-
- `LIST` for **processing tasks** (temporary visibility list)
|
|
30
|
-
- `ZSET` for **visibility timeouts** (invisible tasks until acknowledged or expired)
|
|
31
|
-
- `ZSET` for **delayed scheduling** (future tasks activation)
|
|
37
|
+
---
|
|
32
38
|
|
|
33
|
-
|
|
34
|
-
- high-performance Redis-based backends,
|
|
35
|
-
- telemetry and distributed job systems,
|
|
36
|
-
- retryable or delayed workloads,
|
|
37
|
-
- cron-like task promotion and requeueing.
|
|
39
|
+
## 📦 Installation
|
|
38
40
|
|
|
41
|
+
```bash
|
|
42
|
+
npm install power-queues
|
|
43
|
+
```
|
|
39
44
|
|
|
40
45
|
---
|
|
41
46
|
|
|
42
|
-
##
|
|
47
|
+
## 🧪 Quick Start
|
|
43
48
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- **Concurrent processing** — process multiple jobs in parallel
|
|
47
|
-
- **Retry logic** — exponential backoff with configurable limits
|
|
48
|
-
- **Lifecycle hooks** — extend and customize every phase
|
|
49
|
-
- **Task chaining** — forward results between queues
|
|
50
|
-
- **Lua-optimized reservation** — atomic batch pulls via LMOVE or RPOPLPUSH fallback
|
|
51
|
-
- **Zero dependencies** — built purely on Node.js + PowerRedis + full-utils
|
|
49
|
+
```ts
|
|
50
|
+
import { QueueService } from './queue.service';
|
|
52
51
|
|
|
53
|
-
|
|
52
|
+
const queue = new QueueService();
|
|
54
53
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
// Add tasks
|
|
55
|
+
await queue.addTasks('my_queue', [
|
|
56
|
+
{ payload: { foo: 'bar' } },
|
|
57
|
+
{ payload: { a: 1, b: 2 } },
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
// Run worker
|
|
61
|
+
queue.runQueue();
|
|
59
62
|
```
|
|
60
|
-
PowerQueue works with any Redis client compatible with IORedis interface.
|
|
61
|
-
|
|
62
|
-
## Example Usage
|
|
63
|
-
### 1. Create your custom queue
|
|
64
|
-
```javascript
|
|
65
|
-
import { PowerQueue } from 'power-queue';
|
|
66
|
-
|
|
67
|
-
class EmailQueue extends PowerQueue {
|
|
68
|
-
/**
|
|
69
|
-
* Process a single task payload.
|
|
70
|
-
*/
|
|
71
|
-
async execute(task) {
|
|
72
|
-
console.log('📨 Sending email:', task.payload);
|
|
73
|
-
|
|
74
|
-
// Simulate async work
|
|
75
|
-
await this.wait(200);
|
|
76
|
-
|
|
77
|
-
// Optionally return result
|
|
78
|
-
return { status: 'sent', timestamp: Date.now() };
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
63
|
|
|
82
|
-
|
|
83
|
-
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 🔧 Add Tasks (Bulk)
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
await queue.addTasks('mass_polling', largeArray, {
|
|
70
|
+
approx: true,
|
|
71
|
+
minidWindowMs: 30000,
|
|
72
|
+
maxlen: largeArray.length,
|
|
84
73
|
});
|
|
74
|
+
```
|
|
85
75
|
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 🏗️ Worker Hooks
|
|
79
|
+
|
|
80
|
+
You can override:
|
|
81
|
+
|
|
82
|
+
- `onExecute`
|
|
83
|
+
- `onSuccess`
|
|
84
|
+
- `onError`
|
|
85
|
+
- `onRetry`
|
|
86
|
+
- `onBatchError`
|
|
87
|
+
- `onSelected`
|
|
88
|
+
- `onReady`
|
|
89
|
+
|
|
90
|
+
Example:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
async onExecute(id, payload) {
|
|
94
|
+
console.log('executing', id, payload);
|
|
95
|
+
}
|
|
86
96
|
```
|
|
87
|
-
### 2. Enqueue a new task
|
|
88
|
-
```javascript
|
|
89
|
-
await emailQueue.enqueue('emails', {
|
|
90
|
-
to: 'user@example.com',
|
|
91
|
-
subject: 'Welcome!',
|
|
92
|
-
body: 'Hello and thanks for joining!',
|
|
93
|
-
});
|
|
94
97
|
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 🧱 Architecture Overview
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
Producer → Redis Stream → Consumer Group → Worker → DLQ (optional)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
- Redis Streams store tasks
|
|
107
|
+
- Lua scripts handle trimming, idempotency, stuck recovery
|
|
108
|
+
- Workers fetch tasks via XREADGROUP or Lua select
|
|
109
|
+
- Tasks executed, ACKed, or sent to DLQ
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 🗄️ Dead Letter Queue (DLQ)
|
|
114
|
+
|
|
115
|
+
Failed tasks after `workerMaxRetries` automatically go to:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
<stream>:dlq
|
|
95
119
|
```
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 🧩 Idempotency
|
|
124
|
+
|
|
125
|
+
Guaranteed by 3 keys:
|
|
126
|
+
|
|
127
|
+
- `doneKey`
|
|
128
|
+
- `lockKey`
|
|
129
|
+
- `startKey`
|
|
130
|
+
|
|
131
|
+
This prevents double-execution during retries, crashes, or concurrency.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 🚀 Performance
|
|
136
|
+
|
|
137
|
+
- 10,000+ XADDs/sec
|
|
138
|
+
- Bulk mode: 50,000 operations in one request
|
|
139
|
+
- Extremely low CPU usage due to Lua trimming
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 🏷️ SEO Keywords
|
|
99
144
|
|
|
100
145
|
```
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
-
|
|
105
|
-
- Handle parallel processing with full isolation
|
|
106
|
-
|
|
107
|
-
## Configuration Options
|
|
108
|
-
Each property is strongly typed and fully documented in TypeDoc.
|
|
109
|
-
| Property | Type | Default | Description |
|
|
110
|
-
| ---------------------- | ----------------------------------- | ------- | ---------------------------------------------- |
|
|
111
|
-
| `iterationTimeout` | `number` | `1000` | Delay (ms) between polling loops |
|
|
112
|
-
| `portionLength` | `number` | `1000` | Max number of tasks per batch pull |
|
|
113
|
-
| `expireStatusSec` | `number` | `300` | TTL for progress tracking |
|
|
114
|
-
| `maxAttempts` | `number` | `1` | Max retry attempts before marking as failed |
|
|
115
|
-
| `concurrency` | `number` | `32` | Parallel runners per queue |
|
|
116
|
-
| `visibilityTimeoutSec` | `number` | `60` | How long a task stays invisible before requeue |
|
|
117
|
-
| `retryBaseSec` | `number` | `1` | Base delay for exponential backoff |
|
|
118
|
-
| `retryMaxSec` | `number` | `3600` | Max retry delay |
|
|
119
|
-
| `runners` | `Map<string, { running: boolean }>` | — | Active queue execution flags |
|
|
120
|
-
| `processingRaw` | `Map<string, string>` | — | Tracks raw Redis entries for acknowledgment |
|
|
121
|
-
| `heartbeatTimers` | `Map<string, NodeJS.Timeout>` | — | Maintains active visibility extensions |
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
## Design Principles
|
|
125
|
-
### Minimalism
|
|
126
|
-
Only core Redis primitives are used — no unnecessary abstractions or event emitters.
|
|
127
|
-
|
|
128
|
-
### Predictability
|
|
129
|
-
All queue state is transparent and Redis-inspectable:
|
|
130
|
-
- ```LIST``` for ready and processing states
|
|
131
|
-
- ```ZSET``` for timeouts and scheduling
|
|
132
|
-
|
|
133
|
-
### Resilience
|
|
134
|
-
Every step (reserve, ack, retry, promote) can recover after process restart.
|
|
135
|
-
|
|
136
|
-
### Extensibility
|
|
137
|
-
Implement custom behaviors by overriding:
|
|
138
|
-
```javascript
|
|
139
|
-
async beforeExecute(task) {}
|
|
140
|
-
async afterExecute(task, result) {}
|
|
141
|
-
async onError(task, error) {}
|
|
142
|
-
async onRetry(task, delaySec) {}
|
|
146
|
+
redis streams, redis queue, task queue, job queue, nodejs queue, nestjs queue,
|
|
147
|
+
bulk xadd, distributed queue system, background jobs, retries, dlq,
|
|
148
|
+
idempotency, redis lua scripts, microservices, high-performance queue,
|
|
149
|
+
high-throughput, batching, concurrency control
|
|
143
150
|
```
|
|
144
151
|
|
|
145
|
-
|
|
146
|
-
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 📜 License
|
|
155
|
+
|
|
156
|
+
MIT
|
package/package.json
CHANGED