queen-mq 0.3.1 → 0.4.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.
Files changed (39) hide show
  1. package/README.md +212 -144
  2. package/client-js/client-v2/Queen.js +28 -0
  3. package/client-js/client-v2/README.md +6 -2
  4. package/client-js/client-v2/builders/QueueBuilder.js +7 -1
  5. package/client-js/client-v2/builders/TransactionBuilder.js +20 -4
  6. package/client-js/client-v2/stream/StreamBuilder.js +72 -0
  7. package/client-js/client-v2/stream/StreamConsumer.js +156 -0
  8. package/client-js/client-v2/stream/Window.js +140 -0
  9. package/client-js/test-v2/MAINTENANCE_TEST.md +148 -0
  10. package/client-js/test-v2/consume.js +1 -0
  11. package/client-js/test-v2/maintenance.js +261 -0
  12. package/client-js/test-v2/retention.js +69 -0
  13. package/client-js/test-v2/run.js +7 -1
  14. package/package.json +1 -1
  15. package/client-js/client/client.js +0 -1536
  16. package/client-js/client/index.js +0 -4
  17. package/client-js/client/utils/http.js +0 -173
  18. package/client-js/client/utils/loadBalancer.js +0 -152
  19. package/client-js/client/utils/retry.js +0 -41
  20. package/client-js/services/encryptionService.js +0 -82
  21. package/client-js/services/evictionService.js +0 -160
  22. package/client-js/services/retentionService.js +0 -162
  23. package/client-js/services/startupSync.js +0 -35
  24. package/client-js/test/README.md +0 -224
  25. package/client-js/test/advanced-client-tests.js +0 -761
  26. package/client-js/test/advanced-pattern-tests.js +0 -1137
  27. package/client-js/test/bus-mode-tests.js +0 -361
  28. package/client-js/test/core-tests.js +0 -457
  29. package/client-js/test/edge-case-tests.js +0 -562
  30. package/client-js/test/enterprise-tests.js +0 -637
  31. package/client-js/test/human.js +0 -162
  32. package/client-js/test/partition-locking-tests.js +0 -545
  33. package/client-js/test/partition-transaction-tests.js +0 -482
  34. package/client-js/test/qos0-tests.js +0 -334
  35. package/client-js/test/test-new.js +0 -370
  36. package/client-js/test/utils.js +0 -169
  37. package/client-js/test/window-buffer-test.js +0 -114
  38. package/client-js/utils/logger.js +0 -44
  39. package/client-js/utils/uuid.js +0 -5
package/README.md CHANGED
@@ -2,15 +2,16 @@
2
2
 
3
3
  <div align="center">
4
4
 
5
- **A modern, high-performance message queue system built on PostgreSQL**
5
+ **A modern, performant message queue system built on PostgreSQL**
6
6
 
7
7
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE.md)
8
8
  [![Node](https://img.shields.io/badge/node-%3E%3D22.0.0-brightgreen.svg)](https://nodejs.org/)
9
+ [![C++](https://img.shields.io/badge/C%2B%2B-17-blue.svg)](https://en.cppreference.com/w/cpp/17)
9
10
 
10
- [Quick Start](#js-client-usage-v2) • [Complete V2 Guide](client-js/client-v2/README.md) • [Examples](#-examples) • [Webapp](#webapp) • [Server Setup](#install-server-and-configure-it) • [HTTP API](#raw-http-api)
11
+ [Quick Start](#one-single-example) • [Complete V2 Guide](client-js/client-v2/README.md) • [Webapp](#webapp) • [Server Setup](#install-the-server-and-configure-it) • [HTTP API](#raw-http-api)
11
12
 
12
13
  <p align="center">
13
- <img src="assets/queen-logo-rose.svg" alt="Queen Logo" width="120" />
14
+ <img src="assets/queen-logo.svg" alt="Queen Logo" width="120" />
14
15
  </p>
15
16
 
16
17
  </div>
@@ -29,6 +30,7 @@ Here are the main features:
29
30
  - Unlimited FIFO partitions within queues
30
31
  - Queue semantics like RabbitMQ
31
32
  - Consumer groups over queues like Kafka
33
+ - Allows for all the patterns you need, from simple queues to complex workflows and request/response patterns
32
34
  - QoS levels: Exactly-once delivery (with transactionId), at-least-once delivery, and at-most-once delivery
33
35
  - Subscription modes for replay (new messages only or from a specific timestamp) and message history control
34
36
  - Transactions between operations (push and ack mainly) for atomicity
@@ -36,19 +38,88 @@ Here are the main features:
36
38
  - Lease renewal for long-running tasks
37
39
  - Message tracing for debugging workflows
38
40
  - Encryption of messages at DB level
41
+ - Automatic message retention and cleanup - Configurable per-queue retention policies
42
+ - Streaming capabilities for real-time aggregation and processing of messages
43
+ - A nice webapp for monitoring and managing the system
44
+ - Maintenace mode that allows to continue pushing messages even when the database is down, and to drain the messages to the database when the maintenance mode is disabled
39
45
 
40
- The system consists of a PostgreSQL database, a replicated server that can be scaled horizontally (though it won't be the bottleneck), and a client library for interacting with the server. All client-server communication happens over HTTP, and the client library is written in JavaScript (support for other languages is planned). There's also a modern Vue 3 web app for monitoring and managing the system.
46
+ The system consists of a PostgreSQL database, a replicated server that can be scaled horizontally (though it won't be the bottleneck), and a client library for interacting with the server. All client-server communication happens over HTTP, and the client library are available for JavaScript and C++ (Other languages like Python are planned). There's also a modern Vue 3 web app for monitoring and managing the system.
41
47
 
42
- With proper batching, the system can handle +100k **messages** per second (not req/s) on modest hardware.
48
+ With proper batching, the system can handle +200k **messages** per second (not req/s) on modest hardware.
43
49
 
44
50
  Main documentation:
45
- - [Client Guide](client-js/client-v2/README.md)
51
+ - [Client Guide JS](client-js/client-v2/README.md)
52
+ - [Client Guide C++](client-cpp/README.md)
46
53
  - [Server Guide](server/README.md)
47
- - [API Reference](API.md)
54
+ - [Streaming Guide](docs/STREAMING_USAGE.md)
55
+ - [API Reference](server/API.md)
56
+ - [Message Retention & Cleanup](docs/RETENTION.md)
48
57
  - [Webapp](webapp/README.md)
58
+ - [Expose the Webapp behind a proxy](proxy/README.md)
49
59
 
60
+ ## Concepts
50
61
 
51
- ## JS Client Usage
62
+ Although the system is designed to be simple to use (not really), there are some concepts that are important to understand to use the system effectively.
63
+
64
+ ### Queues
65
+
66
+ Queues are a way to organize your messages into logical groups. Each queue is like a container for messages. You can have as many queues as you want, and you can configure each queue with different settings, like the lease time, retry limit, encryption, retention, priority, delayed processing, window buffer and retention.
67
+
68
+ ### Partitions
69
+
70
+ Partitions are a way to organize your messages into logical ordered groups. Each partition is like a separate queue inside a queue, and messages in the same partition are guaranteed to be processed in order. Only one consumer/client can acquire the lock for a partition at a time. You can have as many partitions as you want, and you can have as many consumers/clients as you want. If the lease in not acknowledged in time, the message is released and can be acquired by another consumer/client. Use renewLease() to renew the lease during long-running tasks. Each different consumer group can acquire the lock for a partition independently, so you can have as many consumer groups as you want.
71
+
72
+ ### Default partition and consumer group
73
+
74
+ The default partition (if not specified) is `Default`. If you don't specify a consumer group, the messages are processed in queue mode, that is creating a default consumer group named `__QUEUE_MODE__`. Each queue can be used at the same time by multiple consumer groups, and each consumer group can process messages from multiple partitions.
75
+
76
+ ### Consumer groups
77
+
78
+ Consumer groups are a way to process messages for different purposes. Each consumer group is like a separate queue, and messages in the same consumer group partition are guaranteed to be processed in order. Each consumer group tracks its own position in the queue. You can start a consumer group from the beginning of the queue, from a specific timestamp, or only new messages.
79
+
80
+ ### Subscription modes
81
+
82
+ Subscription modes are a way to control the message history that is processed. You can choose to process all messages (including historical ones), only new messages, or messages from a specific timestamp. Subscription modes are only available when using consumer groups.
83
+
84
+ ### Long polling (waiting for messages)
85
+
86
+ The client works with the pull model for pop operations, meaning that you need to explicitly request messages from the queue. Pop and consume mehtods can "wait" server side for messages to be available. When the method is called with wait=true, the method will block until messages are available or the timeout is reached. When the timeout is reached, the method returns an empty array. Long polling is a very efficient way to wait for messages, and it is the recommended way to consume messages.
87
+
88
+ ### Lease renewal
89
+
90
+ Lease renewal is a way to keep the lock for a partition or consumer group alive. You can use lease renewal to prevent the lock from expiring and being acquired by another consumer/client.
91
+
92
+ ### Ack and Nack
93
+
94
+ Ack and Nack are the way to acknowledge or not a message. Ack means that the message has been processed successfully, and Nack means that the message has not been processed successfully. Ack/Nack requires the partitionId, the transactionId and the leaseId to be specified. If the ack is coming from a consumer group, the consumer group name is also required. This logic is handled automatically by the client library, you don't need to worry about it. If the message has already been acknowledged, the ack will be ignored. Based on the configuration, the message can be automatically acknowledged or manually acknowledged.
95
+
96
+ ### Transactions
97
+
98
+ Transactions are a way to ensure that a group of operations are atomic. You can use transactions to ensure that a group of operations are executed together, and if one of the operations fails, the entire transaction is rolled back. Transactions are useful to achieve the exactly-once guarantee. You can process a message on a queue, and forward to the next queue only if the consumer lease is still valid, concatenating ack and push into a single transaction.
99
+
100
+ ### Dead letter queue
101
+
102
+ The dead letter queue is a way to handle messages that are not processed successfully. When a message is not processed successfully, it is moved to the dead letter queue. Messages goes in the DLQ when they are NACK after the retry limit is reached. You configure the retry limit for each queue at queue config.
103
+
104
+ ## Comparison with RabbitMQ, Kafka, and NATS
105
+
106
+ For users familiar with existing message queue systems, here's how Queen's semantics and usage patterns compare:
107
+
108
+ ### Conceptual Mapping
109
+
110
+ | Queen Concept | RabbitMQ Equivalent | Kafka Equivalent | NATS Equivalent |
111
+ |---------------|---------------------|------------------|-----------------|
112
+ | Queue | Queue | Topic | Stream (JetStream) |
113
+ | Partition | N/A (queues are single-consumer by default) | Partition | N/A |
114
+ | Consumer Group | Competing Consumers pattern | Consumer Group | Queue Group |
115
+ | Queue Mode (no group) | Exclusive consumer | N/A (always uses groups) | Single subscriber |
116
+ | Lease | Message TTL / Visibility timeout | N/A (commit-based) | Ack wait / nak delay |
117
+ | Ack/Nack | Ack/Nack | Commit offset | Ack/Nak |
118
+ | Transaction | Publisher confirms + consumer acks | Transactional producer/consumer | N/A |
119
+ | Dead Letter Queue | Dead Letter Exchange | N/A (manual) | N/A (manual) |
120
+
121
+
122
+ ## One single example
52
123
 
53
124
  > 📖 **[Complete Guide: client-js/client-v2/README.md](client-js/client-v2/README.md)** - Full tutorial with all features!
54
125
 
@@ -59,131 +130,105 @@ import { Queen } from 'queen-mq'
59
130
  const queen = new Queen('http://localhost:6632')
60
131
 
61
132
  // Create a queue
62
- await queen.queue('tasks').create()
133
+ await queen
134
+ .queue('critical-task')
135
+ .config({
136
+ leaseTime: 10, // 10 seconds to process the messages (seconds)
137
+ })
138
+ .create()
63
139
 
64
140
  // Push messages
65
- await queen.queue('tasks').push([
66
- { data: { job: 'send-email', to: 'alice@example.com' } },
67
- { data: { job: 'process-image', id: 123 } }
141
+ await queen
142
+ .queue('critical-task')
143
+ .partition('tenant-123')
144
+ .push([
145
+ {
146
+ transactionId: 'my-id', // This is autogenerated, but you can set your own. Unique per queue partition.
147
+ data: { id: 123, description: 'Critical task' } // The message payload
148
+ },
68
149
  ])
69
-
70
- // Consume messages (auto-ack on success, auto-nack on error)
71
- await queen.queue('tasks').consume(async (message) => {
72
- console.log('Processing:', message.data)
73
- // If this succeeds → message completed ✅
74
- // If this throws → message retried 🔄
150
+ .onSuccess(async (messages) => { // Not mandatory
151
+ console.log('Messages pushed successfully:', messages)
152
+ })
153
+ .onDuplicate(async (messages) => { // Not mandatory, triggered when a message with the same transactionId is pushed
154
+ console.warn('Duplicate transaction IDs detected')
155
+ })
156
+ .onError(async (messages, error) => { // Without callbacks, push throws an error if some messages are not pushed
157
+ console.error('Error pushing messages:', error)
75
158
  })
76
159
 
77
- // Pop messages manually
78
- const messages = await queen.queue('tasks').batch(10).pop()
79
- for (const msg of messages) {
80
- try {
81
- await processMessage(msg.data)
82
- await queen.ack(msg, true) // Success
83
- } catch (error) {
84
- await queen.ack(msg, false) // Retry
85
- }
86
- }
87
-
88
- // Partitions (for ordering)
89
- await queen
90
- .queue('user-events')
91
- .partition('user-123')
92
- .push([{ data: { event: 'login' } }])
93
-
94
- // Consumer groups (for scaling)
95
- await queen
96
- .queue('emails')
97
- .group('processors')
98
- .concurrency(5)
99
- .consume(async (message) => {
100
- await sendEmail(message.data)
101
- })
102
-
103
- // Subscription modes (control message history)
104
- // Skip historical messages, only process new ones
105
- await queen
106
- .queue('events')
107
- .group('realtime-monitor')
108
- .subscriptionMode('new')
109
- .consume(async (message) => {
110
- console.log('New event only:', message.data)
111
- })
112
-
113
- // Start from a specific timestamp
114
- const timestamp = '2025-10-28T10:00:00.000Z'
115
- await queen
116
- .queue('events')
117
- .group('replay-from-timestamp')
118
- .subscriptionFrom(timestamp)
119
- .consume(async (message) => {
120
- console.log('Replaying from 10am:', message.data)
121
- })
122
-
123
- // Transactions (atomic ack + push)
124
- const [msg] = await queen.queue('input').pop()
160
+ // Consume messages
125
161
  await queen
162
+ .queue('critical-task')
163
+ // The consumer group name, without this, the messages are processed in queue mode
164
+ .group('processor-consumer-group')
165
+ // 10 parallel workers
166
+ .concurrency(10)
167
+ // I want to manually ack/nack messages
168
+ .autoAck(false)
169
+ // 10 messages per batch, prefetch them
170
+ .batch(10)
171
+ // Auto-renew the lease for the messages every 2 seconds
172
+ .renewLease(true, 2000)
173
+ // Process each message individually
174
+ .each()
175
+ // Do your work here
176
+ .consume(async (message) => {
177
+ console.log('Processing:', message.data)
178
+ })
179
+ // Ack the messages if you processed them successfully
180
+ .onSuccess(async (message) => {
181
+ await queen
126
182
  .transaction()
127
- .ack(msg)
128
- .queue('output')
129
- .push([{ data: { processed: true } }])
130
- .commit()
131
-
132
- // Client-side buffering (for high throughput)
133
- await queen
134
- .queue('logs')
135
- .buffer({ messageCount: 100, timeMillis: 1000 })
136
- .push([{ data: { level: 'info', message: 'Server started' } }])
137
-
138
- // Message tracing (for debugging and monitoring)
139
- await queen.queue('orders').consume(async (msg) => {
140
- await msg.trace({
141
- traceName: ['tenant-acme', 'order-flow-123'],
142
- data: { text: 'Processing started', orderId: msg.data.id }
143
- })
144
-
145
- // Process order...
146
-
147
- await msg.trace({
148
- traceName: ['tenant-acme', 'order-flow-123'],
149
- data: { text: 'Order completed' }
150
- })
183
+ .queue('critical-task-next')
184
+ .partition('XXX')
185
+ .push([{ data: { message: 'Final', count: 3 } }])
186
+ .ack(message)
187
+ .commit()
188
+ })
189
+ // Nack the messages if you failed to process them
190
+ .onError(async (message, error) => {
191
+ console.error('Error processing messages:', error)
192
+ await queen.ack(message, false)
151
193
  })
194
+ ```
195
+
196
+ ## Webapp
197
+
198
+ A modern Vue 3 web interface for managing and monitoring Queen MQ.
199
+
200
+ ![Queen MQ Dashboard](./assets/dashboard.png)
152
201
 
153
- // Graceful shutdown
154
- await queen.close()
202
+ ![Queen MQ Queues](./assets/queues.png)
203
+
204
+ ![Queen MQ Messages](./assets/messages.png)
205
+
206
+ ![Queen MQ Traces](./assets/traces.png)
207
+
208
+ ![Queen MQ Analytics](./assets/analytics.png)
209
+
210
+ ![Queen MQ System Metrics](./assets/systemmetrics.png)
211
+
212
+ **Features:**
213
+ - 📊 Real-time dashboard with system metrics
214
+ - 📈 Message throughput visualization
215
+ - 🔍 Queue management and monitoring
216
+ - 👥 Consumer group tracking
217
+ - 💬 Message browser with trace timeline
218
+ - 🔎 **Trace explorer for debugging distributed workflows**
219
+ - 📉 Analytics and insights
220
+ - 🌓 Dark/light theme support
221
+
222
+ **Quick Start:**
223
+ ```bash
224
+ cd webapp
225
+ npm install
226
+ npm run dev
155
227
  ```
156
228
 
157
- **Key Features:**
158
- - ✅ Fluent, chainable API
159
- - ✅ Auto-acknowledgment (or manual control)
160
- - ✅ Partitions for ordered processing
161
- - ✅ Consumer groups for scaling
162
- - ✅ **Subscription modes (new messages only or from timestamp)**
163
- - ✅ Transactions for atomicity
164
- - ✅ Client-side buffering for speed
165
- - ✅ Dead letter queue for failures
166
- - ✅ Lease renewal for long tasks
167
- - ✅ **Message tracing for debugging workflows**
168
- - ✅ Graceful shutdown with buffer flush
169
-
170
- ## 📚 Examples
171
-
172
- ### Client
173
-
174
- See the **[Complete V2 Guide](client-js/client-v2/README.md)** with 14 parts covering everything from basics to advanced features:
175
- - Queue creation, push, and consume
176
- - Partitions and consumer groups
177
- - **Subscription modes (new messages, timestamps)**
178
- - Transactions and buffering
179
- - Dead letter queues
180
- - Lease renewal
181
- - Message tracing
182
- - Complete real-world pipeline example
183
- - And much more!
184
-
185
- **Test Files** (94 working examples): [client-js/test-v2/](client-js/test-v2/)
229
+ The dashboard will be available at `http://localhost:4000` or at `http://localhost:6632` directly from the server.
186
230
 
231
+ See [webapp/README.md](webapp/README.md) for more details.
187
232
 
188
233
  ## Architecture
189
234
 
@@ -233,32 +278,54 @@ Queen automatically buffers messages to disk when PostgreSQL is unavailable - **
233
278
  FILE_BUFFER_DIR=/custom/path ./bin/queen-server
234
279
  ```
235
280
 
236
- ## Webapp
281
+ ## Performance Benchmarks
237
282
 
238
- A modern Vue 3 web interface for managing and monitoring Queen MQ.
283
+ **Preliminary results from C++ client benchmark** (detailed benchmarks on dedicated hardware coming soon)
239
284
 
240
- **Features:**
241
- - 📊 Real-time dashboard with system metrics
242
- - 📈 Message throughput visualization
243
- - 🔍 Queue management and monitoring
244
- - 👥 Consumer group tracking
245
- - 💬 Message browser with trace timeline
246
- - 🔎 **Trace explorer for debugging distributed workflows**
247
- - 📉 Analytics and insights
248
- - 🌓 Dark/light theme support
285
+ ### Test Environment
286
+ - **Hardware:** Apple M4 Air (all components on same machine, 10 processors available)
287
+ - **Server:** 1 server, 4 workers, 95 total DB connections/threads
288
+ - **Database:** PostgreSQL in Docker
289
+ - **Client:** C++ benchmark tool (`benchmark/bin/benchmark`)
290
+
291
+ ### Results
292
+
293
+ | Mode | Threads | Messages | Batch Size | Partitions | Queue Mode | Throughput | Bandwidth |
294
+ |------|---------|----------|------------|------------|------------|------------|-----------|
295
+ | **Producer** | 100 | 10K | 1 | 100 | single-queue | **1,431 msg/sec** | 0.41 MB/sec |
296
+ | **Producer** | 100 | 10K | 1 | 100 | multi-queue | 527 msg/sec | 0.15 MB/sec |
297
+ | **Producer** | 10 | 1M | 1,000 | 100 | single-queue | **62,927 msg/sec** | 18.00 MB/sec |
298
+ | **Producer** | 10 | 1M | 1,000 | 100 | multi-queue | 49,663 msg/sec | 14.21 MB/sec |
299
+ | **Producer** | 10 | 1M | 10,000 | 10 | single-queue | 30,351 msg/sec | 8.68 MB/sec |
300
+ | **Consumer** | 10 | 1M | 1,000 | 100 | single-queue | **31,922 msg/sec** | 16.25 MB/sec |
301
+ | **Consumer** | 10 | 1M | 10,000 | 10 | single-queue | **82,974 msg/sec** | 42.25 MB/sec |
302
+
303
+ ### Key Observations
304
+
305
+ - ✅ **Batch size matters:** Larger batches (1,000-10,000) dramatically improve throughput
306
+ - ✅ **Single-queue mode faster:** Better partition-level parallelism than multi-queue
307
+ - ✅ **Consumer performance:** Scales well with batch size (82K msg/sec with 10K batches)
308
+ - ✅ **Producer peak:** 62K msg/sec with optimal batch size (1,000)
309
+ - ⚠️ **Small batches:** Performance drops significantly with batch=1 (lock contention)
310
+
311
+ **Note:** All timing metrics exclude idle timeouts and measure actual message processing time (first message → last message).
312
+
313
+ ### Run Your Own Benchmarks
249
314
 
250
- **Quick Start:**
251
315
  ```bash
252
- cd webapp
253
- npm install
254
- npm run dev
255
- ```
316
+ cd benchmark
317
+ make
256
318
 
257
- The dashboard will be available at `http://localhost:4000`
319
+ # Producer
320
+ ./bin/benchmark producer --threads 10 --count 1000000 --batch 1000 --partitions 100 --mode single-queue
258
321
 
259
- See [webapp/README.md](webapp/README.md) for more details.
322
+ # Consumer
323
+ ./bin/benchmark consumer --threads 10 --batch 1000 --partitions 100 --mode single-queue
324
+ ```
325
+
326
+ See [benchmark/README.md](benchmark/README.md) for detailed usage.
260
327
 
261
- ## Install server and configure it
328
+ ## Install the server and configure it
262
329
 
263
330
  ### Quick Start
264
331
 
@@ -296,7 +363,7 @@ Includes:
296
363
 
297
364
  You can use Queen directly from HTTP without the JS client.
298
365
 
299
- [Here the complete list of API endpoints](API.md)
366
+ [Here the complete list of API endpoints](server/API.md)
300
367
 
301
368
  ## ⚠️ Known Issues & Roadmap
302
369
 
@@ -312,6 +379,7 @@ You can use Queen directly from HTTP without the JS client.
312
379
 
313
380
 
314
381
  ### Other TODO Items
315
- - retention jobs
316
- - auth
317
- - streaming engine
382
+ - Mini streaming engine
383
+ - Proper concurrency on clients
384
+ - Check client failover
385
+ - Py client
@@ -8,6 +8,8 @@ import { LoadBalancer } from './http/LoadBalancer.js'
8
8
  import { BufferManager } from './buffer/BufferManager.js'
9
9
  import { QueueBuilder } from './builders/QueueBuilder.js'
10
10
  import { TransactionBuilder } from './builders/TransactionBuilder.js'
11
+ import { StreamBuilder } from './stream/StreamBuilder.js'
12
+ import { StreamConsumer } from './stream/StreamConsumer.js'
11
13
  import { CLIENT_DEFAULTS } from './utils/defaults.js'
12
14
  import { validateUrl, validateUrls } from './utils/validation.js'
13
15
  import * as logger from './utils/logger.js'
@@ -355,6 +357,32 @@ export class Queen {
355
357
  return stats
356
358
  }
357
359
 
360
+ // ===========================
361
+ // Streaming API
362
+ // ===========================
363
+
364
+ /**
365
+ * Define a stream for windowed processing
366
+ * @param {string} name - Stream name
367
+ * @param {string} namespace - Stream namespace
368
+ * @returns {StreamBuilder}
369
+ */
370
+ stream(name, namespace) {
371
+ logger.log('Queen.stream', { name, namespace })
372
+ return new StreamBuilder(this.#httpClient, this, name, namespace)
373
+ }
374
+
375
+ /**
376
+ * Create a consumer for a stream
377
+ * @param {string} streamName - Stream name
378
+ * @param {string} consumerGroup - Consumer group
379
+ * @returns {StreamConsumer}
380
+ */
381
+ consumer(streamName, consumerGroup) {
382
+ logger.log('Queen.consumer', { streamName, consumerGroup })
383
+ return new StreamConsumer(this.#httpClient, this, streamName, consumerGroup)
384
+ }
385
+
358
386
  // ===========================
359
387
  // Graceful Shutdown
360
388
  // ===========================
@@ -28,8 +28,12 @@ Welcome to Queen client! This is your friendly guide to mastering message queues
28
28
 
29
29
  First, install and import:
30
30
 
31
+ ```sh
32
+ npm install queen-mq
33
+ ```
34
+
31
35
  ```javascript
32
- import { Queen } from './client-js/client-v2/index.js'
36
+ import { Queen } from 'queen-mq'
33
37
 
34
38
  // Connect to your Queen server
35
39
  const queen = new Queen('http://localhost:6632')
@@ -1874,7 +1878,7 @@ process.on('SIGINT', async () => {
1874
1878
  You now know everything about Queen v2! 🎉
1875
1879
 
1876
1880
  **Additional resources:**
1877
- - [API Documentation](../../API.md) - Complete API reference
1881
+ - [API Documentation](../../server/API.md) - Complete API reference
1878
1882
  - [Test Examples](../test-v2/) - 94 working test cases
1879
1883
  - [Architecture Guide](../../docs/) - Deep dive into Queen's internals
1880
1884
 
@@ -2,7 +2,13 @@
2
2
  * Queue builder for fluent API
3
3
  */
4
4
 
5
- import { generateUUID } from '../../utils/uuid.js'
5
+ import { v7 as uuidv7 } from 'uuid';
6
+
7
+ export const generateUUID = () => {
8
+ return uuidv7();
9
+ };
10
+
11
+ //import { generateUUID } from '../../utils/uuid.js'
6
12
  import { isValidUUID } from '../utils/validation.js'
7
13
  import { QUEUE_DEFAULTS, CONSUME_DEFAULTS, POP_DEFAULTS } from '../utils/defaults.js'
8
14
  import * as logger from '../utils/logger.js'
@@ -48,12 +48,19 @@ export class TransactionBuilder {
48
48
  }
49
49
 
50
50
  queue(queueName) {
51
- // Return a sub-builder for push operations
52
- return {
51
+ // Return a sub-builder for push operations with partition support
52
+ let partition = null
53
+
54
+ const subBuilder = {
55
+ partition: (partitionKey) => {
56
+ partition = partitionKey
57
+ return subBuilder
58
+ },
59
+
53
60
  push: (items) => {
54
61
  const itemArray = Array.isArray(items) ? items : [items]
55
62
 
56
- logger.log('TransactionBuilder.queue.push', { queue: queueName, count: itemArray.length })
63
+ logger.log('TransactionBuilder.queue.push', { queue: queueName, partition, count: itemArray.length })
57
64
 
58
65
  this.#operations.push({
59
66
  type: 'push',
@@ -68,16 +75,25 @@ export class TransactionBuilder {
68
75
  payloadValue = item
69
76
  }
70
77
 
71
- return {
78
+ const result = {
72
79
  queue: queueName,
73
80
  payload: payloadValue
74
81
  }
82
+
83
+ // Add partition if set
84
+ if (partition !== null) {
85
+ result.partition = partition
86
+ }
87
+
88
+ return result
75
89
  })
76
90
  })
77
91
 
78
92
  return this
79
93
  }
80
94
  }
95
+
96
+ return subBuilder
81
97
  }
82
98
 
83
99
  async commit() {
@@ -0,0 +1,72 @@
1
+ /**
2
+ * StreamBuilder - Fluent API for defining streams
3
+ */
4
+ export class StreamBuilder {
5
+ constructor(httpClient, queen, name, namespace) {
6
+ this.httpClient = httpClient;
7
+ this.queen = queen;
8
+ this.config = {
9
+ name,
10
+ namespace,
11
+ source_queue_names: [],
12
+ partitioned: false,
13
+ window_type: 'tumbling',
14
+ window_duration_ms: 60000, // 1 minute default
15
+ window_grace_period_ms: 30000, // 30 seconds default
16
+ window_lease_timeout_ms: 60000 // 1 minute default
17
+ };
18
+ }
19
+
20
+ /**
21
+ * Set the source queues for this stream
22
+ * @param {string[]} queueNames - Array of queue names
23
+ */
24
+ sources(queueNames = []) {
25
+ this.config.source_queue_names = queueNames;
26
+ return this;
27
+ }
28
+
29
+ /**
30
+ * Enable partitioned processing (group by partition_id)
31
+ */
32
+ partitioned() {
33
+ this.config.partitioned = true;
34
+ return this;
35
+ }
36
+
37
+ /**
38
+ * Configure tumbling time window
39
+ * @param {number} seconds - Window duration in seconds
40
+ */
41
+ tumblingTime(seconds) {
42
+ this.config.window_type = 'tumbling';
43
+ this.config.window_duration_ms = seconds * 1000;
44
+ return this;
45
+ }
46
+
47
+ /**
48
+ * Configure grace period for late-arriving messages
49
+ * @param {number} seconds - Grace period in seconds
50
+ */
51
+ gracePeriod(seconds) {
52
+ this.config.window_grace_period_ms = seconds * 1000;
53
+ return this;
54
+ }
55
+
56
+ /**
57
+ * Configure lease timeout
58
+ * @param {number} seconds - Lease timeout in seconds
59
+ */
60
+ leaseTimeout(seconds) {
61
+ this.config.window_lease_timeout_ms = seconds * 1000;
62
+ return this;
63
+ }
64
+
65
+ /**
66
+ * Define/create the stream on the server
67
+ */
68
+ async define() {
69
+ return this.httpClient.post('/api/v1/stream/define', this.config);
70
+ }
71
+ }
72
+