@usermetrics/queuebit 1.0.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/docs/API.md ADDED
@@ -0,0 +1,577 @@
1
+ # QueueBit API Documentation
2
+
3
+ QueueBit is a high-performance, socket-based message queue system with guaranteed delivery.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Server API](#server-api)
8
+ - [Client API](#client-api)
9
+ - [Message Format](#message-format)
10
+ - [Examples](#examples)
11
+
12
+ ---
13
+
14
+ ## Server API
15
+
16
+ ### QueueBitServer
17
+
18
+ The server class that handles message queuing and delivery.
19
+
20
+ #### Constructor
21
+
22
+ Creates a new QueueBit server instance.
23
+
24
+ ```javascript
25
+ const { QueueBitServer } = require('queuebit');
26
+
27
+ const server = new QueueBitServer(options);
28
+ ```
29
+
30
+ **Options:**
31
+
32
+ | Parameter | Type | Default | Description |
33
+ |-----------|------|---------|-------------|
34
+ | `port` | number | 3000 | Port number for the server |
35
+ | `maxQueueSize` | number | 10000 | Maximum messages per subject |
36
+
37
+ **Example:**
38
+
39
+ ```javascript
40
+ const server = new QueueBitServer({
41
+ port: 3000,
42
+ maxQueueSize: 50000
43
+ });
44
+ ```
45
+
46
+ #### close()
47
+
48
+ Shuts down the server and closes all connections.
49
+
50
+ ```javascript
51
+ server.close();
52
+ ```
53
+
54
+ **Example:**
55
+
56
+ ```javascript
57
+ // Graceful shutdown
58
+ process.on('SIGINT', () => {
59
+ console.log('Shutting down...');
60
+ server.close();
61
+ process.exit(0);
62
+ });
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Client API
68
+
69
+ ### QueueBitClient
70
+
71
+ The client class for connecting to a QueueBit server.
72
+
73
+ #### Constructor
74
+
75
+ Creates a new client connection to the server.
76
+
77
+ ```javascript
78
+ const { QueueBitClient } = require('queuebit');
79
+
80
+ const client = new QueueBitClient(url);
81
+ ```
82
+
83
+ **Parameters:**
84
+
85
+ | Parameter | Type | Default | Description |
86
+ |-----------|------|---------|-------------|
87
+ | `url` | string | 'http://localhost:3000' | Server URL |
88
+
89
+ **Example:**
90
+
91
+ ```javascript
92
+ // Node.js
93
+ const { QueueBitClient } = require('queuebit');
94
+ const client = new QueueBitClient('http://localhost:3000');
95
+
96
+ // Browser
97
+ const client = new QueueBitClient('http://localhost:3000');
98
+ ```
99
+
100
+ ---
101
+
102
+ ### publish(message, options)
103
+
104
+ Publishes a message to the queue.
105
+
106
+ **Parameters:**
107
+
108
+ | Parameter | Type | Required | Description |
109
+ |-----------|------|----------|-------------|
110
+ | `message` | object | Yes | The message data (must be a JSON object) |
111
+ | `options` | object | No | Publishing options |
112
+
113
+ **Options:**
114
+
115
+ | Option | Type | Description |
116
+ |--------|------|-------------|
117
+ | `subject` | string | Subject/topic for routing (default: 'default') |
118
+ | `expiry` | Date | Expiration date for the message |
119
+ | `removeAfterRead` | boolean | Remove message after first delivery (default: false) |
120
+
121
+ **Returns:** Promise<{ success: boolean, messageId?: string, error?: string }>
122
+
123
+ **Examples:**
124
+
125
+ ```javascript
126
+ // Basic publish
127
+ const result = await client.publish({
128
+ text: 'Hello, World!'
129
+ });
130
+ console.log(result); // { success: true, messageId: 'uuid-here' }
131
+
132
+ // Publish to specific subject
133
+ await client.publish(
134
+ { orderId: 12345, status: 'pending' },
135
+ { subject: 'orders' }
136
+ );
137
+
138
+ // Ephemeral message (removed after first read)
139
+ await client.publish(
140
+ { notification: 'System update' },
141
+ { removeAfterRead: true }
142
+ );
143
+
144
+ // Message with expiry (expires in 1 hour)
145
+ const expiryDate = new Date(Date.now() + 3600000);
146
+ await client.publish(
147
+ { tempData: 'expires soon' },
148
+ {
149
+ subject: 'temp',
150
+ expiry: expiryDate
151
+ }
152
+ );
153
+ ```
154
+
155
+ ---
156
+
157
+ ### subscribe(callback, options)
158
+
159
+ Subscribes to messages from the queue.
160
+
161
+ **Parameters:**
162
+
163
+ | Parameter | Type | Required | Description |
164
+ |-----------|------|----------|-------------|
165
+ | `callback` | function | Yes | Function called when message is received |
166
+ | `options` | object | No | Subscription options |
167
+
168
+ **Options:**
169
+
170
+ | Option | Type | Description |
171
+ |--------|------|-------------|
172
+ | `subject` | string | Subscribe to specific subject (default: 'default') |
173
+ | `queue` | string | Join a queue group for load-balanced delivery |
174
+
175
+ **Callback Signature:**
176
+
177
+ ```javascript
178
+ (message: QueueMessage) => void
179
+ ```
180
+
181
+ **Returns:** Promise<{ success: boolean, subject?: string, queue?: string }>
182
+
183
+ **Examples:**
184
+
185
+ ```javascript
186
+ // Basic subscription
187
+ await client.subscribe((message) => {
188
+ console.log('Received:', message.data);
189
+ });
190
+
191
+ // Subscribe to specific subject
192
+ await client.subscribe(
193
+ (message) => {
194
+ console.log('Order received:', message.data);
195
+ },
196
+ { subject: 'orders' }
197
+ );
198
+
199
+ // Queue group (load-balanced across multiple subscribers)
200
+ await client.subscribe(
201
+ (message) => {
202
+ console.log('Processing task:', message.data);
203
+ // Only one subscriber in the group receives this message
204
+ },
205
+ {
206
+ subject: 'tasks',
207
+ queue: 'workers'
208
+ }
209
+ );
210
+
211
+ // Multiple subjects
212
+ await client.subscribe(
213
+ (message) => console.log('High priority:', message.data),
214
+ { subject: 'priority.high' }
215
+ );
216
+
217
+ await client.subscribe(
218
+ (message) => console.log('Low priority:', message.data),
219
+ { subject: 'priority.low' }
220
+ );
221
+ ```
222
+
223
+ ---
224
+
225
+ ### unsubscribe(options)
226
+
227
+ Unsubscribes from messages.
228
+
229
+ **Parameters:**
230
+
231
+ | Parameter | Type | Required | Description |
232
+ |-----------|------|----------|-------------|
233
+ | `options` | object | No | Unsubscription options |
234
+
235
+ **Options:**
236
+
237
+ | Option | Type | Description |
238
+ |--------|------|-------------|
239
+ | `subject` | string | Subject to unsubscribe from (default: 'default') |
240
+ | `queue` | string | Queue group to leave |
241
+
242
+ **Returns:** Promise<{ success: boolean }>
243
+
244
+ **Examples:**
245
+
246
+ ```javascript
247
+ // Unsubscribe from default subject
248
+ await client.unsubscribe();
249
+
250
+ // Unsubscribe from specific subject
251
+ await client.unsubscribe({ subject: 'orders' });
252
+
253
+ // Leave queue group
254
+ await client.unsubscribe({
255
+ subject: 'tasks',
256
+ queue: 'workers'
257
+ });
258
+ ```
259
+
260
+ ---
261
+
262
+ ### getMessages(options)
263
+
264
+ Retrieves all messages currently in the queue for a subject.
265
+
266
+ **Parameters:**
267
+
268
+ | Parameter | Type | Required | Description |
269
+ |-----------|------|----------|-------------|
270
+ | `options` | object | No | Query options |
271
+
272
+ **Options:**
273
+
274
+ | Option | Type | Description |
275
+ |--------|------|-------------|
276
+ | `subject` | string | Subject to query (default: 'default') |
277
+
278
+ **Returns:** Promise<{ success: boolean, messages: QueueMessage[], count: number }>
279
+
280
+ **Examples:**
281
+
282
+ ```javascript
283
+ // Get all messages from default subject
284
+ const result = await client.getMessages();
285
+ console.log(`Found ${result.count} messages`);
286
+ result.messages.forEach(msg => {
287
+ console.log(msg.data);
288
+ });
289
+
290
+ // Get messages from specific subject
291
+ const orders = await client.getMessages({ subject: 'orders' });
292
+ console.log(`${orders.count} pending orders`);
293
+ ```
294
+
295
+ ---
296
+
297
+ ### disconnect()
298
+
299
+ Disconnects from the server.
300
+
301
+ ```javascript
302
+ client.disconnect();
303
+ ```
304
+
305
+ **Example:**
306
+
307
+ ```javascript
308
+ // Clean disconnect
309
+ await client.unsubscribe();
310
+ client.disconnect();
311
+ ```
312
+
313
+ ---
314
+
315
+ ## Message Format
316
+
317
+ ### QueueMessage
318
+
319
+ Every message in QueueBit has the following structure:
320
+
321
+ ```typescript
322
+ {
323
+ id: string, // Unique message identifier (UUID)
324
+ data: object, // Your message payload
325
+ subject: string, // Message subject/topic
326
+ timestamp: Date, // When message was published
327
+ expiry?: Date, // Optional expiration date
328
+ removeAfterRead: boolean // Whether to remove after first read
329
+ }
330
+ ```
331
+
332
+ **Example:**
333
+
334
+ ```javascript
335
+ {
336
+ id: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
337
+ data: { orderId: 12345, amount: 99.99 },
338
+ subject: 'orders',
339
+ timestamp: '2024-01-15T10:30:00.000Z',
340
+ expiry: null,
341
+ removeAfterRead: false
342
+ }
343
+ ```
344
+
345
+ ---
346
+
347
+ ## Examples
348
+
349
+ ### Basic Pub/Sub
350
+
351
+ ```javascript
352
+ const { QueueBitServer, QueueBitClient } = require('queuebit');
353
+
354
+ // Start server
355
+ const server = new QueueBitServer({ port: 3000 });
356
+
357
+ // Create clients
358
+ const publisher = new QueueBitClient('http://localhost:3000');
359
+ const subscriber = new QueueBitClient('http://localhost:3000');
360
+
361
+ // Subscribe
362
+ await subscriber.subscribe((message) => {
363
+ console.log('Received:', message.data);
364
+ });
365
+
366
+ // Publish
367
+ await publisher.publish({ text: 'Hello, World!' });
368
+ ```
369
+
370
+ ### Request-Response Pattern
371
+
372
+ ```javascript
373
+ // Responder
374
+ await responder.subscribe(async (message) => {
375
+ const { requestId, question } = message.data;
376
+
377
+ // Process request
378
+ const answer = processQuestion(question);
379
+
380
+ // Send response
381
+ await responder.publish(
382
+ { requestId, answer },
383
+ { subject: 'responses' }
384
+ );
385
+ }, { subject: 'requests' });
386
+
387
+ // Requester
388
+ const requestId = generateId();
389
+
390
+ // Listen for response
391
+ await requester.subscribe((message) => {
392
+ if (message.data.requestId === requestId) {
393
+ console.log('Answer:', message.data.answer);
394
+ }
395
+ }, { subject: 'responses' });
396
+
397
+ // Send request
398
+ await requester.publish(
399
+ { requestId, question: 'What is 2+2?' },
400
+ { subject: 'requests' }
401
+ );
402
+ ```
403
+
404
+ ### Work Queue Pattern
405
+
406
+ ```javascript
407
+ // Producer
408
+ for (let i = 0; i < 100; i++) {
409
+ await producer.publish(
410
+ { taskId: i, work: `Task ${i}` },
411
+ { subject: 'tasks' }
412
+ );
413
+ }
414
+
415
+ // Worker 1
416
+ await worker1.subscribe((message) => {
417
+ console.log('Worker 1 processing:', message.data.taskId);
418
+ }, { subject: 'tasks', queue: 'workers' });
419
+
420
+ // Worker 2
421
+ await worker2.subscribe((message) => {
422
+ console.log('Worker 2 processing:', message.data.taskId);
423
+ }, { subject: 'tasks', queue: 'workers' });
424
+
425
+ // Tasks are distributed between Worker 1 and Worker 2
426
+ ```
427
+
428
+ ### Expiring Messages
429
+
430
+ ```javascript
431
+ // Publish message that expires in 5 minutes
432
+ const expiryDate = new Date(Date.now() + 300000);
433
+
434
+ await client.publish(
435
+ {
436
+ code: 'ABC123',
437
+ description: 'Temporary access code'
438
+ },
439
+ {
440
+ subject: 'temp-codes',
441
+ expiry: expiryDate
442
+ }
443
+ );
444
+
445
+ // Message is automatically removed after expiry
446
+ ```
447
+
448
+ ### One-Time Notifications
449
+
450
+ ```javascript
451
+ // Publisher sends ephemeral notification
452
+ await publisher.publish(
453
+ { alert: 'Server restarting in 5 minutes' },
454
+ {
455
+ subject: 'alerts',
456
+ removeAfterRead: true
457
+ }
458
+ );
459
+
460
+ // First subscriber gets the message
461
+ await subscriber1.subscribe((message) => {
462
+ console.log('Alert:', message.data.alert); // Receives message
463
+ }, { subject: 'alerts' });
464
+
465
+ // Second subscriber connects later
466
+ await subscriber2.subscribe((message) => {
467
+ console.log('Alert:', message.data.alert); // Won't receive it
468
+ }, { subject: 'alerts' });
469
+ ```
470
+
471
+ ### Multi-Topic Subscription
472
+
473
+ ```javascript
474
+ const client = new QueueBitClient('http://localhost:3000');
475
+
476
+ // Subscribe to multiple topics
477
+ await client.subscribe((msg) => {
478
+ console.log('User event:', msg.data);
479
+ }, { subject: 'users' });
480
+
481
+ await client.subscribe((msg) => {
482
+ console.log('Order event:', msg.data);
483
+ }, { subject: 'orders' });
484
+
485
+ await client.subscribe((msg) => {
486
+ console.log('Payment event:', msg.data);
487
+ }, { subject: 'payments' });
488
+
489
+ // Publish to different topics
490
+ await client.publish({ action: 'login' }, { subject: 'users' });
491
+ await client.publish({ orderId: 123 }, { subject: 'orders' });
492
+ await client.publish({ amount: 50 }, { subject: 'payments' });
493
+ ```
494
+
495
+ ---
496
+
497
+ ## Performance Tips
498
+
499
+ 1. **Use subjects** for routing instead of filtering in callbacks
500
+ 2. **Queue groups** for load balancing across multiple consumers
501
+ 3. **Batch publishing** when sending many messages
502
+ 4. **Remove old messages** using expiry to prevent memory issues
503
+ 5. **WebSocket transport** is faster than long-polling (default)
504
+
505
+ ---
506
+
507
+ ## Error Handling
508
+
509
+ ```javascript
510
+ try {
511
+ const result = await client.publish({ data: 'test' });
512
+ if (!result.success) {
513
+ console.error('Publish failed:', result.error);
514
+ }
515
+ } catch (error) {
516
+ console.error('Connection error:', error);
517
+ }
518
+
519
+ // Handle disconnection
520
+ client.socket.on('disconnect', () => {
521
+ console.log('Disconnected from server');
522
+ // Implement reconnection logic
523
+ });
524
+
525
+ client.socket.on('connect_error', (error) => {
526
+ console.error('Connection error:', error);
527
+ });
528
+ ```
529
+
530
+ ---
531
+
532
+ ## Browser Usage
533
+
534
+ Include Socket.IO and QueueBit client in your HTML:
535
+
536
+ ```html
537
+ <script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script>
538
+ <script src="node_modules/queuebit/src/client-browser.js"></script>
539
+
540
+ <script>
541
+ const client = new QueueBitClient('http://localhost:3000');
542
+
543
+ client.subscribe((message) => {
544
+ console.log('Received:', message.data);
545
+ });
546
+
547
+ client.publish({ text: 'Hello from browser!' });
548
+ </script>
549
+ ```
550
+
551
+ ---
552
+
553
+ ## NATS Compatibility
554
+
555
+ QueueBit implements NATS-like patterns:
556
+
557
+ - **Subjects**: Topic-based routing
558
+ - **Queue Groups**: Load-balanced delivery
559
+ - **At-least-once delivery**: Messages persisted until delivered
560
+ - **Wildcards**: Not currently supported (planned)
561
+
562
+ ---
563
+
564
+ ## Best Practices
565
+
566
+ 1. **Use meaningful subject names**: `orders.created`, `users.login`, etc.
567
+ 2. **Set appropriate expiry times** for temporary data
568
+ 3. **Clean up subscriptions** when no longer needed
569
+ 4. **Monitor queue sizes** to prevent memory issues
570
+ 5. **Use queue groups** for scalable message processing
571
+ 6. **Handle reconnection** in production applications
572
+
573
+ ---
574
+
575
+ ## License
576
+
577
+ MIT License - See LICENSE file for details