@usermetrics/queuebit 1.0.6 → 1.0.8

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 CHANGED
@@ -1,8 +1,11 @@
1
1
  # QueueBit
2
2
 
3
3
  A high performance socket-based message queue server with guaranteed delivery, compatible with NATS queue patterns.
4
+
4
5
  Built-in Load Balancer with round-robin delivery. (see examples).
5
6
 
7
+ If you need a pubsub between client and server, or server to server, this is a good choice.
8
+
6
9
  It can run in-process in an existing Node.js app, separately as a standalone server, or run clients
7
10
  in the backend and/or frontend.
8
11
  A frontend in examples (qpanel.html) can help test the server.
@@ -33,13 +36,27 @@ npm install @usermetrics/queuebit
33
36
 
34
37
  ## Quick Start
35
38
 
36
- ### Start the Server
39
+ ### Start the Server in-process with a node app
40
+ #### QueueBit runs with the main app. This can reduce costs for simple apps running the cloud.
37
41
 
38
42
  ```javascript
39
43
  const { QueueBitServer } = require('./src/server');
40
44
  const server = new QueueBitServer({ port: 3333 });
41
45
  ```
42
46
 
47
+ ### Start the Server with monitoring
48
+ ```javascript
49
+ const { QueueBitServer } = require('../../src/server');
50
+ const PORT = 3333;
51
+ new QueueBitServer({ port: PORT,
52
+ monitorInterval: 1000,
53
+ monitorCallback: (data) => {
54
+ console.log(data);
55
+ } });
56
+ ```
57
+
58
+ ### Start the Server as a standalone process
59
+ #### The server runs standalone
43
60
  On Windows:
44
61
  ```cmd
45
62
  start_server.cmd
@@ -93,6 +110,9 @@ setTimeout(async () => {
93
110
 
94
111
  See [`examples/inprocessserver.js`](./examples/inprocessserver.js) for a full example.
95
112
 
113
+ ## Testing Control Panel
114
+ ![QueueBit Control Panel](./docs/screen.jpg)
115
+
96
116
  ## API Overview
97
117
 
98
118
  ### Server Options
Binary file
@@ -5,7 +5,7 @@
5
5
  * run the server with /start_server.cmd and then run this example with /examples/start_node_client.cmd
6
6
  */
7
7
  const http = require('http');
8
- const { QueueBitClient } = require('../src/client-node');
8
+ const { QueueBitClient } = require('../../src/client-node');
9
9
 
10
10
  const webserverPORT = 3000;
11
11
  const queuebitPORT = 3333;
@@ -0,0 +1,2 @@
1
+ echo Ensure QueueBit server is running on port 3333 before starting this client.
2
+ node ./server2server.js
@@ -1,13 +1,16 @@
1
1
  /**
2
2
  * In-process QueueBit demo.
3
3
  * Starts the QueueBit server and an HTTP server in the same process.
4
- * Use the qpanel.html dashboard to publish messages to the queue and see them received by the HTTP server.
4
+ * Use the qpanel.html dashboard (run with live server in vscode) to publish messages to the queue
5
+ * and see them received by the HTTP server.
5
6
  * Run this example with /examples/start_node_inprocess.cmd
6
7
  * No need to run a separate QueueBit server.
8
+ * Pros: Simple setup, good for testing and demos. Lower costs since only one process is running.
9
+ * Cons: If the process crashes, both the queue server and HTTP server go down.
7
10
  */
8
11
  const http = require('http');
9
- const { QueueBitServer } = require('../src/server');
10
- const { QueueBitClient } = require('../src/client-node');
12
+ const { QueueBitServer } = require('../../src/server');
13
+ const { QueueBitClient } = require('../../src/client-node');
11
14
 
12
15
  const webserverPORT = 3000;
13
16
  const queuebitPORT = 3333;
@@ -0,0 +1 @@
1
+ node inprocessserver.js
@@ -3,15 +3,15 @@
3
3
  * Messages are distributed round-robin across workers in the same load balancer.
4
4
  * Only ONE worker receives each message (unlike regular subscribe where ALL receive).
5
5
  *
6
+ * Flow: Server Receives Message | Server sends to next worker in line for that load balancer id
7
+ * Each client is given a loadbalancer id (e.g. 'workers').
8
+ * The server keeps track of which client is next in line for each loadbalancer id.
6
9
  * Run this example with: node examples/queuegroup.js
7
10
  */
8
- const { QueueBitServer } = require('../src/server');
9
- const { QueueBitClient } = require('../src/client-node');
10
11
 
11
- const PORT = 3333;
12
+ const { QueueBitClient } = require('../../src/client-node');
12
13
 
13
- // Start QueueBit server in-process
14
- new QueueBitServer({ port: PORT });
14
+ const PORT = 3333;
15
15
 
16
16
  async function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
17
17
 
@@ -45,7 +45,7 @@ async function main() {
45
45
 
46
46
  for (let i = 1; i <= 6; i++) {
47
47
  await publisher.publish({ job: `task-${i}`, payload: `data-${i}` }, { subject: 'jobs' });
48
- await sleep(100);
48
+ await sleep(1000);
49
49
  }
50
50
 
51
51
  await sleep(500);
@@ -0,0 +1,10 @@
1
+ // simple server wrapper
2
+ // you can start the server with node src/server-runner.js or create your own wrapper like this:
3
+ const { QueueBitServer } = require('../../src/server');
4
+ const PORT = 3333;
5
+ new QueueBitServer({ port: PORT,
6
+ monitorInterval: 1000,
7
+ monitorCallback: (data) => {
8
+ console.log(data);
9
+ } });
10
+ console.log(`QueueBit server running on port ${PORT}`);
@@ -0,0 +1,5 @@
1
+ echo start in command prompt (not bash) to open new terminals for each process
2
+ start node server.js
3
+ start node loadbalancer.js
4
+ start node loadbalancer.js
5
+ start node loadbalancer.js
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Server to server queue.
3
+ * This adds queue functionality to a simple http server (the queue server is running elsewhere)
4
+ * Use the qpanel.html dashboard to publish messages to the queue and see them received by the HTTP server.
5
+ * run the server with /start_server.cmd and then run this example with /examples/start_node_client.cmd
6
+ */
7
+
8
+ const { QueueBitClient } = require('../../src/client-node');
9
+
10
+
11
+ const queuebitPORT = 3333;
12
+
13
+ // Initialize a queuebit message queue. It will connect to the server running on port 3333
14
+ const messageQueue = new QueueBitClient(`http://localhost:${queuebitPORT}`);
15
+
16
+ messageQueue.subscribe((msg) => {
17
+ console.log('Received message from queue:', msg);
18
+ }, { subject: 'default' });
19
+
@@ -0,0 +1,3 @@
1
+ echo Ensure QueueBit server is running on port 3333 before starting this client.
2
+ echo logs all messages to the default queue
3
+ node ./logger.js
@@ -115,7 +115,7 @@
115
115
  <input type="text" id="subject" placeholder="Subject" class="small">
116
116
  <br>
117
117
  <button onclick="publishMessage()">Publish</button>
118
- <button onclick="publishEphemeral()">Ephemeral</button>
118
+ <button onclick="publishEphemeral()">Ephemeral (deliver and delete)</button>
119
119
  </div>
120
120
  </div>
121
121
 
@@ -0,0 +1,11 @@
1
+ // simple server wrapper
2
+ // you can start the server with node src/server-runner.js or create your own wrapper like this:
3
+ // specify monitorInterval to enable server monitoring (logs memory usage and event loop lag every interval ms)
4
+ const { QueueBitServer } = require('../../src/server');
5
+ const PORT = 3333;
6
+ new QueueBitServer({ port: PORT,
7
+ monitorInterval: 1000,
8
+ monitorCallback: (data) => {
9
+ console.log(data);
10
+ } });
11
+ console.log(`QueueBit server running on port ${PORT}`);
@@ -0,0 +1 @@
1
+ node server.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usermetrics/queuebit",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/server.js CHANGED
@@ -7,6 +7,8 @@ class QueueBitServer {
7
7
  const port = options.port || 3000;
8
8
  this.maxQueueSize = options.maxQueueSize || 10000;
9
9
  this.version = packageJson.version;
10
+ this.monitorInterval = options.monitorInterval || null;
11
+ this.monitorCallback = options.monitorCallback || null;
10
12
 
11
13
  this.messages = new Map();
12
14
  this.subscribers = new Map();
@@ -33,6 +35,9 @@ class QueueBitServer {
33
35
  this.setupHandlers();
34
36
  this.startExpiryCheck();
35
37
  this.startDeliveryProcessor();
38
+ if (this.monitorInterval) {
39
+ this.startMonitor(this.monitorInterval);
40
+ }
36
41
 
37
42
  console.log(`QueueBit server v${this.version} listening on port ${port}`);
38
43
  }
@@ -296,6 +301,44 @@ class QueueBitServer {
296
301
  }, 1000); // Check every second
297
302
  }
298
303
 
304
+ startMonitor(interval = 5000) {
305
+ setInterval(() => {
306
+ const stats = {
307
+ timestamp: new Date().toISOString(),
308
+ deliveryQueuePending: this.deliveryQueue.length,
309
+ subjects: {},
310
+ totalMessages: 0,
311
+ totalSubscribers: 0,
312
+ totalLBWorkers: 0,
313
+ loadBalancers: {}
314
+ };
315
+
316
+ for (const [subject, queue] of this.messages.entries()) {
317
+ stats.subjects[subject] = stats.subjects[subject] || {};
318
+ stats.subjects[subject].messages = queue.length;
319
+ stats.totalMessages += queue.length;
320
+ }
321
+
322
+ for (const [subject, subs] of this.subscribers.entries()) {
323
+ stats.subjects[subject] = stats.subjects[subject] || {};
324
+ stats.subjects[subject].subscribers = subs.size;
325
+ stats.totalSubscribers += subs.size;
326
+ }
327
+
328
+ for (const [subject, lbs] of this.loadBalancers.entries()) {
329
+ for (const [lbName, lb] of lbs.entries()) {
330
+ const key = `${subject} | ${lbName}`;
331
+ stats.loadBalancers[key] = lb.sockets.length;
332
+ stats.totalLBWorkers += lb.sockets.length;
333
+ }
334
+ }
335
+
336
+ if (this.monitorCallback) {
337
+ this.monitorCallback(stats);
338
+ }
339
+ }, interval);
340
+ }
341
+
299
342
  close() {
300
343
  this.io.close();
301
344
  }
@@ -1 +0,0 @@
1
- node ./loadbalancer.js
@@ -1 +0,0 @@
1
- node ./server2server.js
@@ -1 +0,0 @@
1
- call node inprocessserver.js