@pingpolls/redisq 0.1.0 → 0.2.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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # RedisQueue
1
+ # RedisQ
2
2
 
3
3
  A lightweight, type-safe Redis-based message queue for Bun with support for delayed messages, retries, and batch processing.
4
4
 
@@ -754,17 +754,28 @@ describe('Queue Tests', () => {
754
754
  Run the stress test to benchmark on your hardware:
755
755
 
756
756
  ```bash
757
- bun run stress-test.ts
757
+ bun stress
758
758
  ```
759
759
 
760
- Expected results on limited 2CPU 2GB Dockerized WSL2 with:
761
- - **Throughput**: ~7,010 messages/second
762
- - **Latency (p50)**: 1.45 ms
763
- - **Latency (p95)**: 3.94 ms
764
- - **Latency (p99)**: 7.83 ms
760
+ Individual Queue Performance:
761
+ - **Tiny messages (100B)**: 47181 msg/s (p50: 49.97ms)
762
+ - **Small messages (1KB)**: 33709 msg/s (p50: 69.05ms)
763
+ - **Medium messages (10KB)**: 4056 msg/s (p50: 261.32ms)
764
+
765
+ Overall:
766
+ - **Throughput**: ~28,315 messages/second
767
+ - **Latency (p50)**: 126.78 ms
768
+ - **Latency (p95)**: 299.27 ms
769
+ - **Latency (p99)**: 383.86 ms
770
+
771
+ Tested on Dockerized `redis:alpine` through WSL2 with 1 CPU and 1GB instance.
765
772
 
766
773
  *Results may vary based on hardware, Redis configuration, and network conditions.*
767
774
 
775
+ ## Contributing
776
+
777
+ Check our github repository [here](https://github.com/pingpolls/redisq).
778
+
768
779
  ## License
769
780
 
770
781
  Apache License 2.0
package/app.test.ts CHANGED
@@ -22,7 +22,7 @@ describe("RedisQueue Tests", () => {
22
22
 
23
23
  await queue.createQueue({ qname: "test-basic" });
24
24
 
25
- const message = "Hello, World!";
25
+ const message = JSON.stringify({ id: 1, name: "John Doe" });
26
26
  let receivedCount = 0;
27
27
 
28
28
  const id = await queue.sendMessage({
@@ -61,9 +61,9 @@ describe("RedisQueue Tests", () => {
61
61
 
62
62
  const sentAt = Date.now();
63
63
  const id = await queue.sendMessage({
64
+ delay: delayMs,
64
65
  message,
65
66
  qname: "test-delayed",
66
- delay: delayMs,
67
67
  });
68
68
 
69
69
  await new Promise<void>((resolve) => {
@@ -100,9 +100,9 @@ describe("RedisQueue Tests", () => {
100
100
  const queue = new RedisQueue(redisConfig);
101
101
 
102
102
  await queue.createQueue({
103
- qname: "test-retry",
104
- maxRetries: 3,
105
103
  maxBackoffSeconds: 1,
104
+ maxRetries: 3,
105
+ qname: "test-retry",
106
106
  });
107
107
 
108
108
  const message = "Retry me!";
@@ -144,9 +144,9 @@ describe("RedisQueue Tests", () => {
144
144
  const queue = new RedisQueue(redisConfig);
145
145
 
146
146
  await queue.createQueue({
147
- qname: "test-delayed-retry",
148
- maxRetries: 2,
149
147
  maxBackoffSeconds: 1,
148
+ maxRetries: 2,
149
+ qname: "test-delayed-retry",
150
150
  });
151
151
 
152
152
  const message = "Delayed retry message";
@@ -155,9 +155,9 @@ describe("RedisQueue Tests", () => {
155
155
 
156
156
  const sentAt = Date.now();
157
157
  await queue.sendMessage({
158
+ delay: delayMs,
158
159
  message,
159
160
  qname: "test-delayed-retry",
160
- delay: delayMs,
161
161
  });
162
162
 
163
163
  await new Promise<void>((resolve) => {
@@ -205,9 +205,9 @@ describe("RedisQueue Tests", () => {
205
205
  * This simulates a spreadsheet-queue:batch with shorter period for testing
206
206
  */
207
207
  await queue.createQueue({
208
- qname: "spreadsheet-queue:batch",
209
208
  every: 3,
210
209
  maxRetries: 0,
210
+ qname: "spreadsheet-queue:batch",
211
211
  });
212
212
 
213
213
  /**
@@ -235,9 +235,9 @@ describe("RedisQueue Tests", () => {
235
235
  for (let i = 1; i <= 6; i++) {
236
236
  const message = `Spreadsheet row ${i} for batch-001`;
237
237
  await queue.sendBatchMessage({
238
- qname: "spreadsheet-queue:batch",
239
238
  batchId: "batch-001",
240
239
  message,
240
+ qname: "spreadsheet-queue:batch",
241
241
  });
242
242
  batch001Messages.push(message);
243
243
  }
@@ -248,9 +248,9 @@ describe("RedisQueue Tests", () => {
248
248
  for (let i = 1; i <= 4; i++) {
249
249
  const message = `Spreadsheet row ${i} for batch-002`;
250
250
  await queue.sendBatchMessage({
251
- qname: "spreadsheet-queue:batch",
252
251
  batchId: "batch-002",
253
252
  message,
253
+ qname: "spreadsheet-queue:batch",
254
254
  });
255
255
  batch002Messages.push(message);
256
256
  }
@@ -334,10 +334,10 @@ describe("RedisQueue Tests", () => {
334
334
  * Create batch queue with 2-second interval and retry enabled
335
335
  */
336
336
  await queue.createQueue({
337
- qname: "retry-test:batch",
338
337
  every: 2,
339
- maxRetries: 3,
340
338
  maxBackoffSeconds: 1,
339
+ maxRetries: 3,
340
+ qname: "retry-test:batch",
341
341
  });
342
342
 
343
343
  const processedBatches: Array<{
@@ -351,9 +351,9 @@ describe("RedisQueue Tests", () => {
351
351
  */
352
352
  for (let i = 1; i <= 3; i++) {
353
353
  await queue.sendBatchMessage({
354
- qname: "retry-test:batch",
355
354
  batchId: `batch-00${i}`,
356
355
  message: `Message ${i}`,
356
+ qname: "retry-test:batch",
357
357
  });
358
358
  }
359
359
 
@@ -365,8 +365,8 @@ describe("RedisQueue Tests", () => {
365
365
  "retry-test:batch",
366
366
  async (received) => {
367
367
  processedBatches.push({
368
- batchId: received.batchId,
369
368
  attempt: received.attempt,
369
+ batchId: received.batchId,
370
370
  success: false,
371
371
  });
372
372
 
@@ -505,6 +505,51 @@ describe("RedisQueue Tests", () => {
505
505
 
506
506
  await queue.close();
507
507
  });
508
+
509
+ test("7. Can handle high volume and concurrency", async () => {
510
+ const totalMessages = 10_000;
511
+
512
+ const queue = new RedisQueue(redisConfig);
513
+
514
+ await queue.createQueue({ qname: "test-concurrency" });
515
+
516
+ const processedIds: string[] = [];
517
+
518
+ Array.from({ length: totalMessages }, async (_, i) => {
519
+ await queue.sendMessage({
520
+ message: JSON.stringify({
521
+ id: `${i}`,
522
+ name: `John Doe ${i}`,
523
+ }),
524
+ qname: "test-concurrency",
525
+ });
526
+ });
527
+
528
+ let receivedCount = 0;
529
+
530
+ await new Promise<void>((resolve) => {
531
+ queue.startWorker(
532
+ "test-concurrency",
533
+ async (received) => {
534
+ receivedCount++;
535
+ processedIds.push(JSON.parse(received.message).id);
536
+ if (receivedCount === totalMessages) {
537
+ resolve();
538
+ }
539
+ return { success: true };
540
+ },
541
+ workerConfig,
542
+ );
543
+ });
544
+
545
+ for (let i = 0; i < totalMessages; i++) {
546
+ expect(processedIds[i]).toBe(`${i}`);
547
+ }
548
+
549
+ expect(receivedCount).toBe(totalMessages);
550
+
551
+ await queue.close();
552
+ });
508
553
  });
509
554
 
510
555
  afterAll(async () => {
package/app.ts CHANGED
@@ -200,14 +200,25 @@ export class RedisQueue {
200
200
 
201
201
  async deleteQueue(qname: string): Promise<boolean> {
202
202
  const pattern = `${this.ns}:${qname}*`;
203
- const keys = await this.redis.keys(pattern);
204
-
205
- if (keys.length === 0) {
206
- return false;
207
- }
203
+ let cursor = "0";
204
+ let keysFound = false;
205
+
206
+ do {
207
+ const [nextCursor, keys] = await this.redis.scan(
208
+ cursor,
209
+ "MATCH",
210
+ pattern,
211
+ "COUNT",
212
+ 500,
213
+ );
214
+ cursor = nextCursor as string;
215
+ if (keys.length > 0) {
216
+ keysFound = true;
217
+ await this.redis.del(...keys);
218
+ }
219
+ } while (cursor !== "0");
208
220
 
209
- await this.redis.del(...keys);
210
- return true;
221
+ return keysFound;
211
222
  }
212
223
 
213
224
  async sendMessage(options: SendMessageOptions): Promise<string> {
@@ -295,10 +306,11 @@ export class RedisQueue {
295
306
  const batchKey = this.getKey(qname, `batch:${batchId}`);
296
307
  const batchMetaKey = this.getKey(qname, "batch-meta");
297
308
 
298
- await this.redis.hset(messagesKey, { [id]: encoded });
299
- await this.redis.sadd(batchKey, id);
300
-
301
- const batchExists = await this.redis.hexists(batchMetaKey, batchId);
309
+ const [_, __, batchExists] = await Promise.all([
310
+ this.redis.hset(messagesKey, { [id]: encoded }),
311
+ this.redis.sadd(batchKey, id),
312
+ this.redis.hexists(batchMetaKey, batchId),
313
+ ]);
302
314
 
303
315
  if (!batchExists) {
304
316
  const batchMeta: StoredBatchMeta = {
@@ -345,27 +357,6 @@ export class RedisQueue {
345
357
  return JSON.parse(encoded);
346
358
  }
347
359
 
348
- private async fetchMessage(
349
- qname: string,
350
- id: string,
351
- ): Promise<Message | null> {
352
- const messagesKey = this.getKey(qname, "messages");
353
- const encoded = await this.redis.hget(messagesKey, id);
354
-
355
- if (!encoded) {
356
- return null;
357
- }
358
-
359
- const stored = this.decodeMessage(encoded);
360
- return {
361
- attempt: stored.attempt,
362
- id: stored.id,
363
- message: stored.message,
364
- sent: stored.sent,
365
- };
366
- }
367
-
368
- // OPTIMIZED: Batch fetch multiple messages at once
369
360
  private async fetchMessages(
370
361
  qname: string,
371
362
  ids: string[],
@@ -674,7 +665,6 @@ export class RedisQueue {
674
665
  }
675
666
  }
676
667
 
677
- // OPTIMIZED: Process messages in parallel within worker
678
668
  private async runWorker(
679
669
  qname: string,
680
670
  handler: (message: Message) => Promise<{ success: boolean }>,
@@ -683,22 +673,21 @@ export class RedisQueue {
683
673
  silent: boolean,
684
674
  ): Promise<void> {
685
675
  const queueKey = this.getKey(qname, "queue");
676
+ const BATCH_SIZE = 50;
686
677
 
687
678
  while (!signal.aborted) {
688
679
  try {
689
680
  await this.processDelayedMessages(qname);
690
681
 
691
- const result = await this.redis.send("BRPOP", [
692
- queueKey,
693
- "0.1",
694
- ]);
682
+ const ids = await this.redis.rpop(queueKey, BATCH_SIZE);
695
683
 
696
- if (result && Array.isArray(result) && result.length >= 2) {
697
- const id = result[1] as string;
698
- const message = await this.fetchMessage(qname, id);
684
+ if (ids && ids.length > 0) {
685
+ const messages = await this.fetchMessages(
686
+ qname,
687
+ ids as string[],
688
+ );
699
689
 
700
- if (message) {
701
- // Process message without blocking the loop
690
+ const processingPromises = messages.map((message) =>
702
691
  handler(message)
703
692
  .then(async ({ success }) => {
704
693
  if (success) {
@@ -715,8 +704,11 @@ export class RedisQueue {
715
704
  );
716
705
  }
717
706
  await this.retryMessage(qname, message.id);
718
- });
719
- }
707
+ }),
708
+ );
709
+ await Promise.all(processingPromises);
710
+ } else {
711
+ await Bun.sleep(50);
720
712
  }
721
713
  } catch (error) {
722
714
  if (!signal.aborted) {
@@ -0,0 +1 @@
1
+ [{"_id":"6973b4f29af00ad243d8dfb1","index":0,"guid":"3da3f9d7-2406-4f07-8cc5-20c77a18ade4","isActive":false,"balance":"$1,361.82","picture":"http://placehold.it/32x32","age":37,"eyeColor":"green","name":"Hart Booth","gender":"male","company":"SULTRAX","email":"hartbooth@sultrax.com","phone":"+1 (966) 498-3673","address":"843 Hall Street, Trona, Oregon, 1712","about":"Deserunt fugiat nisi voluptate quis ex nisi reprehenderit est eiusmod officia sunt quis elit ea. Quis non mollit consectetur amet nulla anim ipsum consequat aliqua reprehenderit tempor reprehenderit. Sint pariatur pariatur laboris sint dolor sint voluptate pariatur ut adipisicing officia Lorem deserunt. Ullamco minim duis sit consequat aliqua in sunt nostrud amet nisi deserunt voluptate pariatur. Qui ullamco aliquip sunt veniam occaecat nulla ex incididunt. Aute mollit incididunt ad in dolor culpa pariatur non commodo magna nostrud non.\r\n","registered":"2025-07-22T10:26:43 -07:00","latitude":-3.647469,"longitude":69.437957,"tags":["qui","est","aliqua","ullamco","eiusmod","eu","velit"],"friends":[{"id":0,"name":"Lakisha Turner"},{"id":1,"name":"Leonor Ewing"},{"id":2,"name":"Frazier Irwin"}],"greeting":"Hello, Hart Booth! You have 6 unread messages.","favoriteFruit":"banana"},{"_id":"6973b4f2021b2c498f984bb6","index":1,"guid":"25034ff5-fbc8-4d09-8c63-e60f919e9ad4","isActive":false,"balance":"$2,141.41","picture":"http://placehold.it/32x32","age":33,"eyeColor":"brown","name":"Bethany Davenport","gender":"female","company":"STROZEN","email":"bethanydavenport@strozen.com","phone":"+1 (818) 499-2890","address":"506 Quay Street, Springville, Texas, 5249","about":"Consectetur occaecat sunt consectetur culpa nulla qui sunt labore proident et irure fugiat eu nulla. Voluptate est dolore labore aliqua velit duis. Proident occaecat culpa esse deserunt nulla aliqua. Nulla ea minim esse consectetur fugiat nostrud in anim esse cillum. Quis dolor quis reprehenderit ex ex ad esse minim est.\r\n","registered":"2020-08-03T11:36:56 -07:00","latitude":-10.479417,"longitude":28.341411,"tags":["non","eiusmod","amet","cillum","incididunt","elit","exercitation"],"friends":[{"id":0,"name":"Phyllis Bryan"},{"id":1,"name":"Mallory Gill"},{"id":2,"name":"Schneider Mercado"}],"greeting":"Hello, Bethany Davenport! You have 9 unread messages.","favoriteFruit":"apple"},{"_id":"6973b4f2220a607ed78df07a","index":2,"guid":"871776e1-d133-4ae7-8343-4fca929bb75c","isActive":true,"balance":"$2,630.76","picture":"http://placehold.it/32x32","age":35,"eyeColor":"brown","name":"Bertie Peters","gender":"female","company":"PERKLE","email":"bertiepeters@perkle.com","phone":"+1 (841) 517-3179","address":"972 Nassau Street, Ventress, Wyoming, 585","about":"Fugiat reprehenderit excepteur deserunt magna laboris aute culpa. Voluptate amet nisi commodo nostrud ipsum do nisi consectetur sint deserunt qui sint proident. Consequat cupidatat deserunt aliquip aliqua occaecat velit ad nostrud deserunt qui. Sunt amet sunt voluptate reprehenderit nisi eiusmod deserunt ea cillum Lorem qui anim aute duis.\r\n","registered":"2025-08-27T03:50:35 -07:00","latitude":32.284355,"longitude":-78.324272,"tags":["consequat","id","voluptate","tempor","proident","non","occaecat"],"friends":[{"id":0,"name":"Foreman Quinn"},{"id":1,"name":"Rojas Kemp"},{"id":2,"name":"Hanson Buck"}],"greeting":"Hello, Bertie Peters! You have 3 unread messages.","favoriteFruit":"banana"},{"_id":"6973b4f2bd348f1a31aca9f8","index":3,"guid":"fc19928a-b4f9-441e-ade9-efd7bad779af","isActive":false,"balance":"$1,273.51","picture":"http://placehold.it/32x32","age":40,"eyeColor":"blue","name":"Rosales Sims","gender":"male","company":"CANOPOLY","email":"rosalessims@canopoly.com","phone":"+1 (869) 427-3088","address":"153 Guernsey Street, Ona, New Jersey, 183","about":"Laborum sit sunt ad deserunt velit nisi culpa pariatur est ea mollit. Velit excepteur nulla cupidatat reprehenderit laboris sint amet duis exercitation dolore voluptate commodo sit Lorem. Velit exercitation ea incididunt adipisicing voluptate occaecat.\r\n","registered":"2017-11-04T12:50:51 -07:00","latitude":0.771702,"longitude":82.991386,"tags":["cillum","qui","sint","consectetur","eiusmod","consequat","ex"],"friends":[{"id":0,"name":"Imogene Lamb"},{"id":1,"name":"Key Burris"},{"id":2,"name":"Reyna Mayer"}],"greeting":"Hello, Rosales Sims! You have 7 unread messages.","favoriteFruit":"apple"},{"_id":"6973b4f207f65e544265d355","index":4,"guid":"abc15ba6-3214-4ef8-ac30-8afb642b82c2","isActive":true,"balance":"$2,945.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"brown","name":"Gretchen Jordan","gender":"female","company":"ANOCHA","email":"gretchenjordan@anocha.com","phone":"+1 (948) 454-2346","address":"890 Monaco Place, Loomis, Alabama, 4341","about":"Nulla excepteur est consequat velit aute laborum sunt voluptate aute eu eiusmod. Anim sunt eu veniam in commodo sit eu. Anim commodo incididunt ad reprehenderit anim culpa sit ut. Laborum esse in pariatur velit. Ut elit adipisicing magna ut officia non magna exercitation incididunt enim esse magna ad veniam. Deserunt irure ut dolor dolore labore pariatur veniam ipsum voluptate sint enim dolor. Ad exercitation sint sit occaecat excepteur eiusmod et sit.\r\n","registered":"2022-03-30T04:45:03 -07:00","latitude":29.089418,"longitude":-41.417872,"tags":["minim","amet","aliqua","excepteur","irure","et","culpa"],"friends":[{"id":0,"name":"Sonia Hayden"},{"id":1,"name":"Levy Burks"},{"id":2,"name":"Wolfe Hancock"}],"greeting":"Hello, Gretchen Jordan! You have 5 unread messages.","favoriteFruit":"banana"},{"_id":"6973b4f250d546997251a3d3","index":5,"guid":"ec6af806-cb4c-4ecc-b208-68b4b3cafd93","isActive":false,"balance":"$2,535.09","picture":"http://placehold.it/32x32","age":33,"eyeColor":"brown","name":"Ruiz Tran","gender":"male","company":"AQUASURE","email":"ruiztran@aquasure.com","phone":"+1 (962) 478-3889","address":"705 Farragut Road, Broadlands, Michigan, 1955","about":"Sunt enim Lorem excepteur sint mollit deserunt. Aute commodo amet sit cillum voluptate mollit exercitation ad cillum aute fugiat mollit. Quis ad cupidatat veniam reprehenderit aute cupidatat quis. Minim laboris est fugiat et in cillum id nisi dolore reprehenderit fugiat minim. Nulla ut consequat do sit dolor laboris.\r\n","registered":"2018-09-27T01:51:44 -07:00","latitude":-59.151306,"longitude":143.667188,"tags":["laboris","anim","eiusmod","quis","nulla","aliqua","duis"],"friends":[{"id":0,"name":"Ramona Brock"},{"id":1,"name":"Kayla Webb"},{"id":2,"name":"Rutledge Mcclure"}],"greeting":"Hello, Ruiz Tran! You have 6 unread messages.","favoriteFruit":"apple"},{"_id":"6973b4f20e1b602ed3098386","index":6,"guid":"d63efc08-287a-487e-a159-bbb4f231c37a","isActive":false,"balance":"$3,941.09","picture":"http://placehold.it/32x32","age":37,"eyeColor":"blue","name":"Reba Oneal","gender":"female","company":"NIQUENT","email":"rebaoneal@niquent.com","phone":"+1 (994) 443-2343","address":"229 Clifton Place, Cochranville, Pennsylvania, 6468","about":"Officia veniam do minim elit duis in nulla. Deserunt veniam in ut esse duis nulla cillum magna ullamco dolore veniam exercitation Lorem. Eiusmod pariatur irure dolor aute dolore minim adipisicing sint ullamco. Ipsum id voluptate est ipsum adipisicing est. Do anim exercitation commodo mollit fugiat minim est ea.\r\n","registered":"2020-05-02T09:23:38 -07:00","latitude":-45.360857,"longitude":-17.113491,"tags":["laborum","dolor","incididunt","elit","adipisicing","adipisicing","veniam"],"friends":[{"id":0,"name":"Janine Russell"},{"id":1,"name":"Abby Short"},{"id":2,"name":"Savannah Grant"}],"greeting":"Hello, Reba Oneal! You have 7 unread messages.","favoriteFruit":"banana"},{"_id":"6973b4f208d0cb4b5c53bb93","index":7,"guid":"152d21f2-05cd-41d2-a048-ba499944b2bf","isActive":false,"balance":"$1,155.29","picture":"http://placehold.it/32x32","age":25,"eyeColor":"green","name":"Vanessa Rodriquez","gender":"female","company":"OPTYK","email":"vanessarodriquez@optyk.com","phone":"+1 (873) 492-2951","address":"102 Thatford Avenue, Keyport, Minnesota, 7404","about":"Adipisicing sit dolor reprehenderit Lorem et voluptate culpa ullamco cillum officia dolor culpa et sit. Lorem minim eu laboris nulla do est labore nulla eu occaecat. Est occaecat sit id irure. Enim sint consequat amet mollit occaecat in mollit duis. Eiusmod et tempor laborum est tempor fugiat anim ullamco.\r\n","registered":"2019-11-03T12:06:46 -07:00","latitude":30.194412,"longitude":155.798353,"tags":["aliqua","cupidatat","quis","eiusmod","ad","veniam","velit"],"friends":[{"id":0,"name":"June Little"},{"id":1,"name":"Lamb Marsh"},{"id":2,"name":"Richards Conley"}],"greeting":"Hello, Vanessa Rodriquez! You have 5 unread messages.","favoriteFruit":"banana"},{"_id":"6973b4f244d84ce83babb8e8","index":8,"guid":"2d743ccf-cffe-46ac-821a-1a32180f8401","isActive":true,"balance":"$1,531.94","picture":"http://placehold.it/32x32","age":33,"eyeColor":"brown","name":"Kathy Warren","gender":"female","company":"NURPLEX","email":"kathywarren@nurplex.com","phone":"+1 (958) 514-2617","address":"211 Cypress Court, Rosewood, Massachusetts, 2530","about":"Cillum nisi ad esse aliqua do amet eu dolor. Culpa culpa adipisicing officia nisi magna occaecat aliquip labore nostrud anim. Eu esse in aliquip exercitation reprehenderit cupidatat eu veniam deserunt cillum excepteur id. Id dolor reprehenderit do deserunt. Enim eiusmod nostrud exercitation fugiat consequat. Nulla deserunt cillum mollit excepteur ea ad veniam. Id nostrud laboris ipsum cupidatat ex non commodo ad sunt.\r\n","registered":"2017-06-14T06:01:20 -07:00","latitude":34.733711,"longitude":-163.804679,"tags":["reprehenderit","elit","exercitation","voluptate","aute","adipisicing","occaecat"],"friends":[{"id":0,"name":"Allie Holcomb"},{"id":1,"name":"Muriel Weaver"},{"id":2,"name":"Tommie Carr"}],"greeting":"Hello, Kathy Warren! You have 4 unread messages.","favoriteFruit":"apple"},{"_id":"6973b4f297dc750e1750eb58","index":9,"guid":"1ccffd92-ff08-429d-9232-e86c565e70da","isActive":true,"balance":"$1,662.22","picture":"http://placehold.it/32x32","age":31,"eyeColor":"green","name":"Hodges Richardson","gender":"male","company":"POSHOME","email":"hodgesrichardson@poshome.com","phone":"+1 (970) 590-2870","address":"686 Anna Court, Elizaville, Marshall Islands, 5762","about":"Ullamco cupidatat nisi do ut nostrud est pariatur labore dolore exercitation quis minim ipsum quis. Aute enim excepteur voluptate ullamco laboris adipisicing commodo. Do amet sunt occaecat id commodo. Consectetur veniam excepteur nisi in commodo. Laborum anim dolor velit deserunt culpa. Exercitation do amet laborum do ipsum voluptate commodo. Aliqua exercitation consequat nisi pariatur ea veniam officia nostrud excepteur tempor.\r\n","registered":"2016-07-28T02:54:58 -07:00","latitude":-14.492817,"longitude":134.965697,"tags":["qui","aliquip","pariatur","magna","ad","et","irure"],"friends":[{"id":0,"name":"Robyn Willis"},{"id":1,"name":"Gabrielle Holt"},{"id":2,"name":"Wilkerson Bailey"}],"greeting":"Hello, Hodges Richardson! You have 5 unread messages.","favoriteFruit":"strawberry"},{"_id":"6973b4f277b5d5924e85e34c","index":10,"guid":"24b6f2d6-f153-4826-9c2f-f50c42d907e5","isActive":true,"balance":"$1,715.09","picture":"http://placehold.it/32x32","age":33,"eyeColor":"blue","name":"Floyd Petty","gender":"male","company":"GINKOGENE","email":"floydpetty@ginkogene.com","phone":"+1 (832) 499-3944","address":"910 Canal Avenue, Mammoth, North Dakota, 1708","about":"Eiusmod velit proident sit proident ipsum irure. Excepteur dolore consequat labore duis tempor nulla laborum do amet labore. Amet nisi ullamco ad enim officia id exercitation aliquip in fugiat in. Anim quis et enim proident dolore magna mollit consectetur ea elit velit nostrud. Consectetur ea labore esse esse est nisi consectetur magna ut ullamco nulla ipsum exercitation.\r\n","registered":"2023-09-18T01:14:07 -07:00","latitude":-51.559233,"longitude":134.694377,"tags":["cupidatat","elit","commodo","ullamco","do","reprehenderit","nostrud"],"friends":[{"id":0,"name":"Naomi Garrison"},{"id":1,"name":"Betty English"},{"id":2,"name":"Prince Singleton"}],"greeting":"Hello, Floyd Petty! You have 7 unread messages.","favoriteFruit":"strawberry"},{"_id":"6973b4f2e7ad4e31bb2510c3","index":11,"guid":"74ccb6d9-7f24-4451-a3a0-e632bab385b3","isActive":true,"balance":"$1,490.53","picture":"http://placehold.it/32x32","age":36,"eyeColor":"blue","name":"Johnnie Simon","gender":"female","company":"JAMNATION","email":"johnniesimon@jamnation.com","phone":"+1 (868) 417-3009","address":"125 Chester Street, Whipholt, Maryland, 9466","about":"Dolor anim esse enim Lorem nostrud id officia incididunt amet laboris laboris sunt. Pariatur dolor aute Lorem aute magna. Laborum enim non voluptate commodo.\r\n","registered":"2015-03-03T08:28:39 -07:00","latitude":-19.882734,"longitude":-45.527604,"tags":["qui","sit","culpa","id","dolor","irure","id"],"friends":[{"id":0,"name":"Fry Ayers"},{"id":1,"name":"Donovan Foley"},{"id":2,"name":"Finch Dunn"}],"greeting":"Hello, Johnnie Simon! You have 9 unread messages.","favoriteFruit":"apple"},{"_id":"6973b4f24d0d75c705a54911","index":12,"guid":"f972a1ef-0d3a-41ab-b080-eaf7d26184f1","isActive":true,"balance":"$3,429.83","picture":"http://placehold.it/32x32","age":36,"eyeColor":"brown","name":"Rosalind Duran","gender":"female","company":"ZORROMOP","email":"rosalindduran@zorromop.com","phone":"+1 (987) 589-3940","address":"720 Mill Avenue, Gardiner, Nebraska, 6579","about":"Dolor deserunt nisi laborum eiusmod aliquip adipisicing ullamco eiusmod non qui consectetur est nostrud. Incididunt nostrud labore minim Lorem elit qui commodo consectetur ex culpa veniam. Quis ad quis cillum esse nisi ea ipsum consequat dolore. Non minim minim sint excepteur anim consectetur est voluptate laborum commodo. Mollit ea magna dolor sit ut magna voluptate ipsum reprehenderit id ex cillum deserunt.\r\n","registered":"2014-07-03T10:56:30 -07:00","latitude":-39.091253,"longitude":-131.671201,"tags":["labore","enim","nulla","est","exercitation","ipsum","deserunt"],"friends":[{"id":0,"name":"Emerson Dalton"},{"id":1,"name":"Owen Bass"},{"id":2,"name":"Bell Shannon"}],"greeting":"Hello, Rosalind Duran! You have 1 unread messages.","favoriteFruit":"banana"},{"_id":"6973b4f2edea35a5d2cea142","index":13,"guid":"18cf8f91-9735-4fa6-9381-ae8c1060890c","isActive":true,"balance":"$1,811.69","picture":"http://placehold.it/32x32","age":26,"eyeColor":"blue","name":"Pauline Cain","gender":"female","company":"ENAUT","email":"paulinecain@enaut.com","phone":"+1 (972) 408-3809","address":"508 Rapelye Street, Thynedale, Maine, 9391","about":"Qui enim fugiat do eu in eu aliqua elit cillum occaecat. Consectetur amet pariatur ea dolore Lorem eu ipsum veniam commodo commodo. Mollit dolore velit aliqua cillum elit consequat sunt nostrud in qui ipsum sit eu irure. Cupidatat reprehenderit labore in officia laborum.\r\n","registered":"2023-12-23T01:34:49 -07:00","latitude":-18.152332,"longitude":6.220963,"tags":["quis","sint","proident","officia","dolore","elit","quis"],"friends":[{"id":0,"name":"Kristie Shepherd"},{"id":1,"name":"Jensen Webster"},{"id":2,"name":"Langley Young"}],"greeting":"Hello, Pauline Cain! You have 7 unread messages.","favoriteFruit":"apple"}]
@@ -0,0 +1 @@
1
+ {"batch_id":"batch_analytics_2201","source_system":"inventory_management_v2","generated_at":"2023-10-27T10:00:00Z","record_count":5,"data":[{"sku":"KEY-MECH-RGB-001","warehouse_id":"WH-NY-01","stock_level":450,"reserved":12,"incoming":100,"last_audit":"2023-10-25","dimensions":{"w":15,"h":5,"l":40,"unit":"cm"},"tags":["electronics","peripherals","hot_item"]},{"sku":"MON-4K-IPS-002","warehouse_id":"WH-CA-02","stock_level":85,"reserved":5,"incoming":0,"last_audit":"2023-10-26","dimensions":{"w":60,"h":40,"l":10,"unit":"cm"},"tags":["electronics","display","fragile"]},{"sku":"LAP-PRO-M2-003","warehouse_id":"WH-TX-05","stock_level":200,"reserved":45,"incoming":50,"last_audit":"2023-10-20","dimensions":{"w":30,"h":2,"l":20,"unit":"cm"},"tags":["computer","high_value","insured"]},{"sku":"MOU-ERG-WL-004","warehouse_id":"WH-NY-01","stock_level":1200,"reserved":0,"incoming":200,"last_audit":"2023-10-22","dimensions":{"w":8,"h":5,"l":12,"unit":"cm"},"tags":["peripherals","office","sale"]},{"sku":"CAB-HDMI-2M-005","warehouse_id":"WH-WA-03","stock_level":5000,"reserved":120,"incoming":1000,"last_audit":"2023-10-01","dimensions":{"w":10,"h":2,"l":10,"unit":"cm"},"tags":["accessory","cable","generic"]}],"system_logs":{"warnings":[],"errors":[{"code":404,"msg":"SKU-IMG-MISSING for CAB-HDMI-2M-005","timestamp":1678892500}],"performance_metrics":{"query_time_ms":145,"db_reads":25,"cpu_load_percent":12}}}
@@ -1,4 +1,5 @@
1
1
  import RedisQueue from "../app";
2
+ declare var self: Worker;
2
3
 
3
4
  interface WorkerMessage {
4
5
  type: "start";
@@ -23,15 +24,27 @@ self.addEventListener("message", async (event: MessageEvent<WorkerMessage>) => {
23
24
  try {
24
25
  const queue = new RedisQueue(redisConfig);
25
26
  const latencies: number[] = [];
27
+ const CHUNK_SIZE = 1000;
26
28
 
27
- for (let i = 0; i < messagesPerWorker; i++) {
28
- const start = performance.now();
29
- await queue.sendMessage({
30
- message: testMessage,
31
- qname,
32
- });
33
- const latency = performance.now() - start;
34
- latencies.push(latency);
29
+ for (let i = 0; i < messagesPerWorker; i += CHUNK_SIZE) {
30
+ const promises = [];
31
+ const chunkEnd = Math.min(i + CHUNK_SIZE, messagesPerWorker);
32
+
33
+ for (let j = i; j < chunkEnd; j++) {
34
+ const start = performance.now();
35
+ promises.push(
36
+ queue
37
+ .sendMessage({
38
+ message: testMessage,
39
+ qname,
40
+ })
41
+ .then(() => {
42
+ const latency = performance.now() - start;
43
+ latencies.push(latency);
44
+ }),
45
+ );
46
+ }
47
+ await Promise.all(promises);
35
48
  }
36
49
 
37
50
  await queue.close();
@@ -2,6 +2,9 @@
2
2
 
3
3
  import type { Worker } from "bun";
4
4
  import RedisQueue from "../app";
5
+ import mediumMsg from "./medium.txt";
6
+ import smallMsg from "./small.txt";
7
+ import tinyMsg from "./tiny.txt";
5
8
 
6
9
  const COLORS = {
7
10
  blue: "\x1b[34m",
@@ -14,8 +17,8 @@ const COLORS = {
14
17
  yellow: "\x1b[33m",
15
18
  };
16
19
 
17
- const WORKER_COUNT = 16;
18
- const CONCURRENCY = 50;
20
+ const WORKER_COUNT = 8;
21
+ const CONCURRENCY = 2;
19
22
  const MSG_COUNT = 100_000;
20
23
 
21
24
  interface StressTestConfig {
@@ -112,7 +115,7 @@ async function testRegularQueueParallel(
112
115
  });
113
116
 
114
117
  const qname = "stress-regular";
115
- await queue.createQueue({ maxRetries: 0, qname, maxsize: 150_000 });
118
+ await queue.createQueue({ maxRetries: 0, maxsize: 150_000, qname });
116
119
 
117
120
  const allLatencies: number[] = [];
118
121
  let receivedCount = 0;
@@ -173,7 +176,6 @@ async function testRegularQueueParallel(
173
176
 
174
177
  worker.postMessage({
175
178
  data: {
176
- testMessage: config.testMessage,
177
179
  messagesPerWorker,
178
180
  qname,
179
181
  redisConfig: {
@@ -181,6 +183,7 @@ async function testRegularQueueParallel(
181
183
  namespace: "stress-test",
182
184
  port: process.env.REDIS_PORT || "6379",
183
185
  },
186
+ testMessage: config.testMessage,
184
187
  workerIndex: i,
185
188
  },
186
189
  type: "start",
@@ -261,91 +264,93 @@ async function main() {
261
264
 
262
265
  await cleanup();
263
266
 
264
-
265
- const mediumMessage = '{"batch_id":"batch_analytics_2201","source_system":"inventory_management_v2","generated_at":"2023-10-27T10:00:00Z","record_count":5,"data":[{"sku":"KEY-MECH-RGB-001","warehouse_id":"WH-NY-01","stock_level":450,"reserved":12,"incoming":100,"last_audit":"2023-10-25","dimensions":{"w":15,"h":5,"l":40,"unit":"cm"},"tags":["electronics","peripherals","hot_item"]},{"sku":"MON-4K-IPS-002","warehouse_id":"WH-CA-02","stock_level":85,"reserved":5,"incoming":0,"last_audit":"2023-10-26","dimensions":{"w":60,"h":40,"l":10,"unit":"cm"},"tags":["electronics","display","fragile"]},{"sku":"LAP-PRO-M2-003","warehouse_id":"WH-TX-05","stock_level":200,"reserved":45,"incoming":50,"last_audit":"2023-10-20","dimensions":{"w":30,"h":2,"l":20,"unit":"cm"},"tags":["computer","high_value","insured"]},{"sku":"MOU-ERG-WL-004","warehouse_id":"WH-NY-01","stock_level":1200,"reserved":0,"incoming":200,"last_audit":"2023-10-22","dimensions":{"w":8,"h":5,"l":12,"unit":"cm"},"tags":["peripherals","office","sale"]},{"sku":"CAB-HDMI-2M-005","warehouse_id":"WH-WA-03","stock_level":5000,"reserved":120,"incoming":1000,"last_audit":"2023-10-01","dimensions":{"w":10,"h":2,"l":10,"unit":"cm"},"tags":["accessory","cable","generic"]}],"system_logs":{"warnings":[],"errors":[{"code":404,"msg":"SKU-IMG-MISSING for CAB-HDMI-2M-005","timestamp":1678892500}],"performance_metrics":{"query_time_ms":145,"db_reads":25,"cpu_load_percent":12}}}'
266
-
267
267
  const availableCPUs = navigator.hardwareConcurrency;
268
268
  log("yellow", `\nšŸ’» Detected ${availableCPUs} CPU cores`);
269
269
 
270
270
  log("blue", `\nšŸ”§ Using ${WORKER_COUNT} workers for tests`);
271
271
 
272
272
  try {
273
- // Test 1: Small messages - Maximum throughput
274
- log("cyan", "\nšŸ“‹ Test 1: Small messages (100 bytes)");
273
+ log("cyan", "\nšŸ“‹ Test 1: Tiny messages (100 bytes)");
275
274
  const test1Results = await testRegularQueueParallel({
276
275
  concurrency: CONCURRENCY,
277
276
  messageCount: MSG_COUNT,
278
- testMessage: '{"id":"msg_82103","type":"notification","timestamp":1678892301,"payload":{"user_id":4092,"event":"login_attempt","status":"success"}}',
279
- workerCount:WORKER_COUNT,
277
+ testMessage: tinyMsg,
278
+ workerCount: WORKER_COUNT,
280
279
  });
281
280
  printResults(
282
- "Test 1: Small Messages (50K msgs, 100 bytes)",
281
+ "Test 1: Tiny Messages (100K msgs, 100 bytes)",
283
282
  test1Results,
284
283
  );
285
284
 
285
+ await cleanup();
286
286
 
287
- // Test 2: Medium messages
288
- log("cyan", "\nšŸ“‹ Test 2: Medium messages (1KB)");
287
+ log("cyan", "\nšŸ“‹ Test 2: Small messages (1KB)");
289
288
  const test2Results = await testRegularQueueParallel({
290
289
  concurrency: CONCURRENCY,
291
290
  messageCount: MSG_COUNT,
292
- testMessage: mediumMessage,
293
- workerCount: WORKER_COUNT,
291
+ testMessage: smallMsg,
292
+ workerCount: WORKER_COUNT,
294
293
  });
295
- printResults(
296
- "Test 2: Medium Messages (50K msgs, 1KB)",
297
- test2Results,
298
- );
294
+ printResults("Test 2: Small Messages (100K msgs, 1KB)", test2Results);
299
295
 
296
+ await cleanup();
300
297
 
301
- // Test 3: Large messages
302
- log("cyan", "\nšŸ“‹ Test 3: Large messages (10KB)");
298
+ log("cyan", "\nšŸ“‹ Test 3: Medium messages (10KB)");
303
299
  const test3Results = await testRegularQueueParallel({
304
300
  concurrency: CONCURRENCY,
305
301
  messageCount: MSG_COUNT,
306
- testMessage: '[{"_id":"6973b4f29af00ad243d8dfb1","index":0,"guid":"3da3f9d7-2406-4f07-8cc5-20c77a18ade4","isActive":false,"balance":"$1,361.82","picture":"http://placehold.it/32x32","age":37,"eyeColor":"green","name":"Hart Booth","gender":"male","company":"SULTRAX","email":"hartbooth@sultrax.com","phone":"+1 (966) 498-3673","address":"843 Hall Street, Trona, Oregon, 1712","about":"Deserunt fugiat nisi voluptate quis ex nisi reprehenderit est eiusmod officia sunt quis elit ea. Quis non mollit consectetur amet nulla anim ipsum consequat aliqua reprehenderit tempor reprehenderit. Sint pariatur pariatur laboris sint dolor sint voluptate pariatur ut adipisicing officia Lorem deserunt. Ullamco minim duis sit consequat aliqua in sunt nostrud amet nisi deserunt voluptate pariatur. Qui ullamco aliquip sunt veniam occaecat nulla ex incididunt. Aute mollit incididunt ad in dolor culpa pariatur non commodo magna nostrud non.\r\n","registered":"2025-07-22T10:26:43 -07:00","latitude":-3.647469,"longitude":69.437957,"tags":["qui","est","aliqua","ullamco","eiusmod","eu","velit"],"friends":[{"id":0,"name":"Lakisha Turner"},{"id":1,"name":"Leonor Ewing"},{"id":2,"name":"Frazier Irwin"}],"greeting":"Hello, Hart Booth! You have 6 unread messages.","favoriteFruit":"banana"},{"_id":"6973b4f2021b2c498f984bb6","index":1,"guid":"25034ff5-fbc8-4d09-8c63-e60f919e9ad4","isActive":false,"balance":"$2,141.41","picture":"http://placehold.it/32x32","age":33,"eyeColor":"brown","name":"Bethany Davenport","gender":"female","company":"STROZEN","email":"bethanydavenport@strozen.com","phone":"+1 (818) 499-2890","address":"506 Quay Street, Springville, Texas, 5249","about":"Consectetur occaecat sunt consectetur culpa nulla qui sunt labore proident et irure fugiat eu nulla. Voluptate est dolore labore aliqua velit duis. Proident occaecat culpa esse deserunt nulla aliqua. Nulla ea minim esse consectetur fugiat nostrud in anim esse cillum. Quis dolor quis reprehenderit ex ex ad esse minim est.\r\n","registered":"2020-08-03T11:36:56 -07:00","latitude":-10.479417,"longitude":28.341411,"tags":["non","eiusmod","amet","cillum","incididunt","elit","exercitation"],"friends":[{"id":0,"name":"Phyllis Bryan"},{"id":1,"name":"Mallory Gill"},{"id":2,"name":"Schneider Mercado"}],"greeting":"Hello, Bethany Davenport! You have 9 unread messages.","favoriteFruit":"apple"},{"_id":"6973b4f2220a607ed78df07a","index":2,"guid":"871776e1-d133-4ae7-8343-4fca929bb75c","isActive":true,"balance":"$2,630.76","picture":"http://placehold.it/32x32","age":35,"eyeColor":"brown","name":"Bertie Peters","gender":"female","company":"PERKLE","email":"bertiepeters@perkle.com","phone":"+1 (841) 517-3179","address":"972 Nassau Street, Ventress, Wyoming, 585","about":"Fugiat reprehenderit excepteur deserunt magna laboris aute culpa. Voluptate amet nisi commodo nostrud ipsum do nisi consectetur sint deserunt qui sint proident. Consequat cupidatat deserunt aliquip aliqua occaecat velit ad nostrud deserunt qui. Sunt amet sunt voluptate reprehenderit nisi eiusmod deserunt ea cillum Lorem qui anim aute duis.\r\n","registered":"2025-08-27T03:50:35 -07:00","latitude":32.284355,"longitude":-78.324272,"tags":["consequat","id","voluptate","tempor","proident","non","occaecat"],"friends":[{"id":0,"name":"Foreman Quinn"},{"id":1,"name":"Rojas Kemp"},{"id":2,"name":"Hanson Buck"}],"greeting":"Hello, Bertie Peters! You have 3 unread messages.","favoriteFruit":"banana"},{"_id":"6973b4f2bd348f1a31aca9f8","index":3,"guid":"fc19928a-b4f9-441e-ade9-efd7bad779af","isActive":false,"balance":"$1,273.51","picture":"http://placehold.it/32x32","age":40,"eyeColor":"blue","name":"Rosales Sims","gender":"male","company":"CANOPOLY","email":"rosalessims@canopoly.com","phone":"+1 (869) 427-3088","address":"153 Guernsey Street, Ona, New Jersey, 183","about":"Laborum sit sunt ad deserunt velit nisi culpa pariatur est ea mollit. Velit excepteur nulla cupidatat reprehenderit laboris sint amet duis exercitation dolore voluptate commodo sit Lorem. Velit exercitation ea incididunt adipisicing voluptate occaecat.\r\n","registered":"2017-11-04T12:50:51 -07:00","latitude":0.771702,"longitude":82.991386,"tags":["cillum","qui","sint","consectetur","eiusmod","consequat","ex"],"friends":[{"id":0,"name":"Imogene Lamb"},{"id":1,"name":"Key Burris"},{"id":2,"name":"Reyna Mayer"}],"greeting":"Hello, Rosales Sims! You have 7 unread messages.","favoriteFruit":"apple"},{"_id":"6973b4f207f65e544265d355","index":4,"guid":"abc15ba6-3214-4ef8-ac30-8afb642b82c2","isActive":true,"balance":"$2,945.08","picture":"http://placehold.it/32x32","age":26,"eyeColor":"brown","name":"Gretchen Jordan","gender":"female","company":"ANOCHA","email":"gretchenjordan@anocha.com","phone":"+1 (948) 454-2346","address":"890 Monaco Place, Loomis, Alabama, 4341","about":"Nulla excepteur est consequat velit aute laborum sunt voluptate aute eu eiusmod. Anim sunt eu veniam in commodo sit eu. Anim commodo incididunt ad reprehenderit anim culpa sit ut. Laborum esse in pariatur velit. Ut elit adipisicing magna ut officia non magna exercitation incididunt enim esse magna ad veniam. Deserunt irure ut dolor dolore labore pariatur veniam ipsum voluptate sint enim dolor. Ad exercitation sint sit occaecat excepteur eiusmod et sit.\r\n","registered":"2022-03-30T04:45:03 -07:00","latitude":29.089418,"longitude":-41.417872,"tags":["minim","amet","aliqua","excepteur","irure","et","culpa"],"friends":[{"id":0,"name":"Sonia Hayden"},{"id":1,"name":"Levy Burks"},{"id":2,"name":"Wolfe Hancock"}],"greeting":"Hello, Gretchen Jordan! You have 5 unread messages.","favoriteFruit":"banana"},{"_id":"6973b4f250d546997251a3d3","index":5,"guid":"ec6af806-cb4c-4ecc-b208-68b4b3cafd93","isActive":false,"balance":"$2,535.09","picture":"http://placehold.it/32x32","age":33,"eyeColor":"brown","name":"Ruiz Tran","gender":"male","company":"AQUASURE","email":"ruiztran@aquasure.com","phone":"+1 (962) 478-3889","address":"705 Farragut Road, Broadlands, Michigan, 1955","about":"Sunt enim Lorem excepteur sint mollit deserunt. Aute commodo amet sit cillum voluptate mollit exercitation ad cillum aute fugiat mollit. Quis ad cupidatat veniam reprehenderit aute cupidatat quis. Minim laboris est fugiat et in cillum id nisi dolore reprehenderit fugiat minim. Nulla ut consequat do sit dolor laboris.\r\n","registered":"2018-09-27T01:51:44 -07:00","latitude":-59.151306,"longitude":143.667188,"tags":["laboris","anim","eiusmod","quis","nulla","aliqua","duis"],"friends":[{"id":0,"name":"Ramona Brock"},{"id":1,"name":"Kayla Webb"},{"id":2,"name":"Rutledge Mcclure"}],"greeting":"Hello, Ruiz Tran! You have 6 unread messages.","favoriteFruit":"apple"},{"_id":"6973b4f20e1b602ed3098386","index":6,"guid":"d63efc08-287a-487e-a159-bbb4f231c37a","isActive":false,"balance":"$3,941.09","picture":"http://placehold.it/32x32","age":37,"eyeColor":"blue","name":"Reba Oneal","gender":"female","company":"NIQUENT","email":"rebaoneal@niquent.com","phone":"+1 (994) 443-2343","address":"229 Clifton Place, Cochranville, Pennsylvania, 6468","about":"Officia veniam do minim elit duis in nulla. Deserunt veniam in ut esse duis nulla cillum magna ullamco dolore veniam exercitation Lorem. Eiusmod pariatur irure dolor aute dolore minim adipisicing sint ullamco. Ipsum id voluptate est ipsum adipisicing est. Do anim exercitation commodo mollit fugiat minim est ea.\r\n","registered":"2020-05-02T09:23:38 -07:00","latitude":-45.360857,"longitude":-17.113491,"tags":["laborum","dolor","incididunt","elit","adipisicing","adipisicing","veniam"],"friends":[{"id":0,"name":"Janine Russell"},{"id":1,"name":"Abby Short"},{"id":2,"name":"Savannah Grant"}],"greeting":"Hello, Reba Oneal! You have 7 unread messages.","favoriteFruit":"banana"},{"_id":"6973b4f208d0cb4b5c53bb93","index":7,"guid":"152d21f2-05cd-41d2-a048-ba499944b2bf","isActive":false,"balance":"$1,155.29","picture":"http://placehold.it/32x32","age":25,"eyeColor":"green","name":"Vanessa Rodriquez","gender":"female","company":"OPTYK","email":"vanessarodriquez@optyk.com","phone":"+1 (873) 492-2951","address":"102 Thatford Avenue, Keyport, Minnesota, 7404","about":"Adipisicing sit dolor reprehenderit Lorem et voluptate culpa ullamco cillum officia dolor culpa et sit. Lorem minim eu laboris nulla do est labore nulla eu occaecat. Est occaecat sit id irure. Enim sint consequat amet mollit occaecat in mollit duis. Eiusmod et tempor laborum est tempor fugiat anim ullamco.\r\n","registered":"2019-11-03T12:06:46 -07:00","latitude":30.194412,"longitude":155.798353,"tags":["aliqua","cupidatat","quis","eiusmod","ad","veniam","velit"],"friends":[{"id":0,"name":"June Little"},{"id":1,"name":"Lamb Marsh"},{"id":2,"name":"Richards Conley"}],"greeting":"Hello, Vanessa Rodriquez! You have 5 unread messages.","favoriteFruit":"banana"},{"_id":"6973b4f244d84ce83babb8e8","index":8,"guid":"2d743ccf-cffe-46ac-821a-1a32180f8401","isActive":true,"balance":"$1,531.94","picture":"http://placehold.it/32x32","age":33,"eyeColor":"brown","name":"Kathy Warren","gender":"female","company":"NURPLEX","email":"kathywarren@nurplex.com","phone":"+1 (958) 514-2617","address":"211 Cypress Court, Rosewood, Massachusetts, 2530","about":"Cillum nisi ad esse aliqua do amet eu dolor. Culpa culpa adipisicing officia nisi magna occaecat aliquip labore nostrud anim. Eu esse in aliquip exercitation reprehenderit cupidatat eu veniam deserunt cillum excepteur id. Id dolor reprehenderit do deserunt. Enim eiusmod nostrud exercitation fugiat consequat. Nulla deserunt cillum mollit excepteur ea ad veniam. Id nostrud laboris ipsum cupidatat ex non commodo ad sunt.\r\n","registered":"2017-06-14T06:01:20 -07:00","latitude":34.733711,"longitude":-163.804679,"tags":["reprehenderit","elit","exercitation","voluptate","aute","adipisicing","occaecat"],"friends":[{"id":0,"name":"Allie Holcomb"},{"id":1,"name":"Muriel Weaver"},{"id":2,"name":"Tommie Carr"}],"greeting":"Hello, Kathy Warren! You have 4 unread messages.","favoriteFruit":"apple"},{"_id":"6973b4f297dc750e1750eb58","index":9,"guid":"1ccffd92-ff08-429d-9232-e86c565e70da","isActive":true,"balance":"$1,662.22","picture":"http://placehold.it/32x32","age":31,"eyeColor":"green","name":"Hodges Richardson","gender":"male","company":"POSHOME","email":"hodgesrichardson@poshome.com","phone":"+1 (970) 590-2870","address":"686 Anna Court, Elizaville, Marshall Islands, 5762","about":"Ullamco cupidatat nisi do ut nostrud est pariatur labore dolore exercitation quis minim ipsum quis. Aute enim excepteur voluptate ullamco laboris adipisicing commodo. Do amet sunt occaecat id commodo. Consectetur veniam excepteur nisi in commodo. Laborum anim dolor velit deserunt culpa. Exercitation do amet laborum do ipsum voluptate commodo. Aliqua exercitation consequat nisi pariatur ea veniam officia nostrud excepteur tempor.\r\n","registered":"2016-07-28T02:54:58 -07:00","latitude":-14.492817,"longitude":134.965697,"tags":["qui","aliquip","pariatur","magna","ad","et","irure"],"friends":[{"id":0,"name":"Robyn Willis"},{"id":1,"name":"Gabrielle Holt"},{"id":2,"name":"Wilkerson Bailey"}],"greeting":"Hello, Hodges Richardson! You have 5 unread messages.","favoriteFruit":"strawberry"},{"_id":"6973b4f277b5d5924e85e34c","index":10,"guid":"24b6f2d6-f153-4826-9c2f-f50c42d907e5","isActive":true,"balance":"$1,715.09","picture":"http://placehold.it/32x32","age":33,"eyeColor":"blue","name":"Floyd Petty","gender":"male","company":"GINKOGENE","email":"floydpetty@ginkogene.com","phone":"+1 (832) 499-3944","address":"910 Canal Avenue, Mammoth, North Dakota, 1708","about":"Eiusmod velit proident sit proident ipsum irure. Excepteur dolore consequat labore duis tempor nulla laborum do amet labore. Amet nisi ullamco ad enim officia id exercitation aliquip in fugiat in. Anim quis et enim proident dolore magna mollit consectetur ea elit velit nostrud. Consectetur ea labore esse esse est nisi consectetur magna ut ullamco nulla ipsum exercitation.\r\n","registered":"2023-09-18T01:14:07 -07:00","latitude":-51.559233,"longitude":134.694377,"tags":["cupidatat","elit","commodo","ullamco","do","reprehenderit","nostrud"],"friends":[{"id":0,"name":"Naomi Garrison"},{"id":1,"name":"Betty English"},{"id":2,"name":"Prince Singleton"}],"greeting":"Hello, Floyd Petty! You have 7 unread messages.","favoriteFruit":"strawberry"},{"_id":"6973b4f2e7ad4e31bb2510c3","index":11,"guid":"74ccb6d9-7f24-4451-a3a0-e632bab385b3","isActive":true,"balance":"$1,490.53","picture":"http://placehold.it/32x32","age":36,"eyeColor":"blue","name":"Johnnie Simon","gender":"female","company":"JAMNATION","email":"johnniesimon@jamnation.com","phone":"+1 (868) 417-3009","address":"125 Chester Street, Whipholt, Maryland, 9466","about":"Dolor anim esse enim Lorem nostrud id officia incididunt amet laboris laboris sunt. Pariatur dolor aute Lorem aute magna. Laborum enim non voluptate commodo.\r\n","registered":"2015-03-03T08:28:39 -07:00","latitude":-19.882734,"longitude":-45.527604,"tags":["qui","sit","culpa","id","dolor","irure","id"],"friends":[{"id":0,"name":"Fry Ayers"},{"id":1,"name":"Donovan Foley"},{"id":2,"name":"Finch Dunn"}],"greeting":"Hello, Johnnie Simon! You have 9 unread messages.","favoriteFruit":"apple"},{"_id":"6973b4f24d0d75c705a54911","index":12,"guid":"f972a1ef-0d3a-41ab-b080-eaf7d26184f1","isActive":true,"balance":"$3,429.83","picture":"http://placehold.it/32x32","age":36,"eyeColor":"brown","name":"Rosalind Duran","gender":"female","company":"ZORROMOP","email":"rosalindduran@zorromop.com","phone":"+1 (987) 589-3940","address":"720 Mill Avenue, Gardiner, Nebraska, 6579","about":"Dolor deserunt nisi laborum eiusmod aliquip adipisicing ullamco eiusmod non qui consectetur est nostrud. Incididunt nostrud labore minim Lorem elit qui commodo consectetur ex culpa veniam. Quis ad quis cillum esse nisi ea ipsum consequat dolore. Non minim minim sint excepteur anim consectetur est voluptate laborum commodo. Mollit ea magna dolor sit ut magna voluptate ipsum reprehenderit id ex cillum deserunt.\r\n","registered":"2014-07-03T10:56:30 -07:00","latitude":-39.091253,"longitude":-131.671201,"tags":["labore","enim","nulla","est","exercitation","ipsum","deserunt"],"friends":[{"id":0,"name":"Emerson Dalton"},{"id":1,"name":"Owen Bass"},{"id":2,"name":"Bell Shannon"}],"greeting":"Hello, Rosalind Duran! You have 1 unread messages.","favoriteFruit":"banana"},{"_id":"6973b4f2edea35a5d2cea142","index":13,"guid":"18cf8f91-9735-4fa6-9381-ae8c1060890c","isActive":true,"balance":"$1,811.69","picture":"http://placehold.it/32x32","age":26,"eyeColor":"blue","name":"Pauline Cain","gender":"female","company":"ENAUT","email":"paulinecain@enaut.com","phone":"+1 (972) 408-3809","address":"508 Rapelye Street, Thynedale, Maine, 9391","about":"Qui enim fugiat do eu in eu aliqua elit cillum occaecat. Consectetur amet pariatur ea dolore Lorem eu ipsum veniam commodo commodo. Mollit dolore velit aliqua cillum elit consequat sunt nostrud in qui ipsum sit eu irure. Cupidatat reprehenderit labore in officia laborum.\r\n","registered":"2023-12-23T01:34:49 -07:00","latitude":-18.152332,"longitude":6.220963,"tags":["quis","sint","proident","officia","dolore","elit","quis"],"friends":[{"id":0,"name":"Kristie Shepherd"},{"id":1,"name":"Jensen Webster"},{"id":2,"name":"Langley Young"}],"greeting":"Hello, Pauline Cain! You have 7 unread messages.","favoriteFruit":"apple"}]',
302
+ testMessage: mediumMsg,
307
303
  workerCount: WORKER_COUNT,
308
304
  });
309
- printResults(
310
- "Test 3: Large Messages (50K msgs, 10KB)",
311
- test3Results,
312
- );
305
+ printResults("Test 3: Medium Messages (100K msgs, 10KB)", test3Results);
313
306
 
314
307
  await cleanup();
315
308
 
316
-
309
+ // Calculate combined averages
310
+ const avgThroughput =
311
+ (test1Results.throughput +
312
+ test2Results.throughput +
313
+ test3Results.throughput) /
314
+ 3;
315
+ const avgP50 =
316
+ (test1Results.p50 + test2Results.p50 + test3Results.p50) / 3;
317
+ const avgP95 =
318
+ (test1Results.p95 + test2Results.p95 + test3Results.p95) / 3;
319
+ const avgP99 =
320
+ (test1Results.p99 + test2Results.p99 + test3Results.p99) / 3;
317
321
 
318
322
  // Summary
319
323
  log("bright", `\n${"=".repeat(60)}`);
320
324
  log("magenta", " šŸ“ˆ BENCHMARK SUMMARY");
321
325
  log("bright", "=".repeat(60));
322
326
 
323
- console.log("\n Regular Queue Performance:");
327
+ console.log("\n Individual Queue Performance:");
324
328
  console.log(
325
- ` - Small messages (100B): ${test1Results.throughput.toFixed(0)} msg/s (p50: ${test1Results.p50.toFixed(2)}ms)`,
329
+ ` - Tiny messages (100B): ${test1Results.throughput.toFixed(0)} msg/s (p50: ${test1Results.p50.toFixed(2)}ms)`,
326
330
  );
327
331
  console.log(
328
- ` - Medium messages (1KB): ${test2Results.throughput.toFixed(0)} msg/s (p50: ${test2Results.p50.toFixed(2)}ms)`,
332
+ ` - Small messages (1KB): ${test2Results.throughput.toFixed(0)} msg/s (p50: ${test2Results.p50.toFixed(2)}ms)`,
329
333
  );
330
334
  console.log(
331
- ` - Large messages (100KB): ${test3Results.throughput.toFixed(0)} msg/s (p50: ${test3Results.p50.toFixed(2)}ms)`,
335
+ ` - Medium messages (10KB): ${test3Results.throughput.toFixed(0)} msg/s (p50: ${test3Results.p50.toFixed(2)}ms)`,
332
336
  );
333
337
 
334
- log("bright", "\n" + "=".repeat(60));
338
+ log("bright", `\n${"=".repeat(60)}`);
335
339
 
336
340
  log("green", "\nāœ… All stress tests completed successfully!");
337
341
 
338
342
  log(
339
343
  "yellow",
340
- "\nšŸ’” To update README.md Performance section, use these values:",
344
+ "\nšŸ’” To update README.md Performance section, use these values (averaged across all tests):",
341
345
  );
346
+ console.log("\n Overall:");
342
347
  log(
343
348
  "cyan",
344
- ` - Throughput: ~${Math.round(test1Results.throughput).toLocaleString()} messages/second`,
349
+ ` - **Throughput**: ~${Math.round(avgThroughput).toLocaleString()} messages/second`,
345
350
  );
346
- log("cyan", ` - Latency (p50): ${test1Results.p50.toFixed(2)} ms`);
347
- log("cyan", ` - Latency (p95): ${test1Results.p95.toFixed(2)} ms`);
348
- log("cyan", ` - Latency (p99): ${test1Results.p99.toFixed(2)} ms`);
351
+ log("cyan", ` - **Latency (p50)**: ${avgP50.toFixed(2)} ms`);
352
+ log("cyan", ` - **Latency (p95)**: ${avgP95.toFixed(2)} ms`);
353
+ log("cyan", ` - **Latency (p99)**: ${avgP99.toFixed(2)} ms`);
349
354
  } catch (error) {
350
355
  log(
351
356
  "red",
@@ -0,0 +1 @@
1
+ {"id":"msg_82103","type":"notification","timestamp":1678892301,"payload":{"user_id":4092,"event":"login_attempt","status":"success"}}
package/biome.json CHANGED
@@ -18,7 +18,6 @@
18
18
  "includes": [
19
19
  "./**",
20
20
  "!**/build",
21
- "!benchmark",
22
21
  "!**/node_modules",
23
22
  "!bun.lock",
24
23
  "!bun.lockd"
package/compose.yml CHANGED
@@ -12,6 +12,11 @@ services:
12
12
  - redis-net
13
13
  ports:
14
14
  - 6379:6379
15
+ deploy:
16
+ resources:
17
+ limits:
18
+ cpus: 1
19
+ memory: "1G"
15
20
  volumes:
16
21
  redisvol:
17
22
  driver: local
package/package.json CHANGED
@@ -27,5 +27,5 @@
27
27
  "stress": "bun benchmark/stress.ts"
28
28
  },
29
29
  "type": "module",
30
- "version": "0.1.0"
30
+ "version": "0.2.0"
31
31
  }