power-queues 2.1.9 → 2.1.10

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 (2) hide show
  1. package/README.md +61 -36
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -41,15 +41,18 @@ const queue = new PowerQueues({
41
41
 
42
42
  await queue.loadScripts(true);
43
43
 
44
- await queue.addTasks('mysql_create:example:table_name', [
45
- { type: 'welcome', userId: 42 },
46
- { type: 'hello', userId: 51 }
44
+ await queue.addTasks('ws', [
45
+ { body: 'welcome', userId: 42 },
46
+ { body: 'hello', userId: 51 }
47
47
  ]);
48
48
  ```
49
49
 
50
- Example of a worker for executing a MySQL insert transaction:
50
+ Example of queue worker for sending message to client via WebSocket and executing a MySQL insert transaction:
51
51
 
52
52
  ``` ts
53
+ import express from 'express';
54
+ import http from 'http';
55
+ import { Server } from 'socket.io';
53
56
  import mysql from 'mysql2/promise';
54
57
  import Redis from 'ioredis';
55
58
  import type { IORedisLike } from 'power-redis';
@@ -70,7 +73,11 @@ const pool = mysql.createPool({
70
73
  });
71
74
  const redis = new Redis('redis://127.0.0.1:6379');
72
75
 
73
- export class ExampleQueue extends PowerQueues {
76
+ const app = express();
77
+ const server = http.createServer(app);
78
+ const io = new Server(server);
79
+
80
+ export class WebSocketAndMysqlCreateQueue extends PowerQueues {
74
81
  public readonly selectStuckCount: number = 256;
75
82
  public readonly selectCount: number = 256;
76
83
  public readonly retryCount: number = 3;
@@ -84,50 +91,68 @@ export class ExampleQueue extends PowerQueues {
84
91
  this.redis = redis;
85
92
  }
86
93
 
87
- async onBatchReady(queueName: string, tasks: Task[]) {
88
- const values = tasks
89
- .filter((task) => isObjFilled(task.payload))
90
- .map((task) => task.payload);
91
-
92
- if (isArrFilled(values)) {
93
- const conn = await pool.getConnection();
94
-
95
- try {
96
- await conn.beginTransaction();
97
-
98
- const cols = Object.keys(values[0]);
99
- const placeholder = `(${cols.map(() => '?').join(',')})`;
100
- const sql = `INSERT INTO \`alerts\` (${cols.map((c) => `\`${c}\``).join(',')}) VALUES ${values.map(() => placeholder).join(',')}`;
101
- const params = [];
94
+ async onExecute(queueName: string, task: Task) {
95
+ const id = uuid();
96
+
97
+ io.to(`user:${task.payload.userId}`).emit('alerts', {
98
+ body: task.payload.body,
99
+ id,
100
+ });
101
+ return {
102
+ ...task,
103
+ payload: {
104
+ ...task.payload,
105
+ id,
106
+ },
107
+ };
108
+ }
102
109
 
103
- for (const row of values) {
104
- for (const c of cols) {
105
- params.push(row[c]);
106
- }
110
+ async onBatchReady(queueName: string, tasks: Task[]) {
111
+ const values = tasks.map((task) => task.payload);
112
+ const conn = await pool.getConnection();
113
+
114
+ try {
115
+ await conn.beginTransaction();
116
+
117
+ const cols = Object.keys(values[0]);
118
+ const placeholder = `(${cols.map(() => '?').join(',')})`;
119
+ const sql = `INSERT INTO \`alerts\` (${cols.map((c) => `\`${c}\``).join(',')}) VALUES ${values.map(() => placeholder).join(',')}`;
120
+ const params = [];
121
+
122
+ for (const row of values) {
123
+ for (const c of cols) {
124
+ params.push(row[c]);
107
125
  }
108
- await conn.execute(sql, params);
109
- await conn.commit();
110
- }
111
- catch (err) {
112
- await conn.rollback();
113
- throw err;
114
- }
115
- finally {
116
- conn.release();
117
126
  }
127
+ await conn.execute(sql, params);
128
+ await conn.commit();
129
+ }
130
+ catch (err) {
131
+ await queryRunner.rollbackTransaction();
132
+ throw err;
133
+ }
134
+ finally {
135
+ await queryRunner.release();
118
136
  }
119
137
  }
120
138
 
139
+ async onError(err: any, queueName: string, task: Task): Promise<Task> {
140
+ console.error('Alert error', queueName, task, (process.env.NODE_ENV === 'production')
141
+ ? err.message
142
+ : err);
143
+ return task;
144
+ }
145
+
121
146
  async onBatchError(err: any, queueName: string, tasks: Array<[ string, any, number, string, string, number ]>) {
122
- this.logger.error('Transaction error', queueName, tasks.length, (process.env.NODE_ENV === 'production')
147
+ console.error('Batch error', queueName, tasks.length, (process.env.NODE_ENV === 'production')
123
148
  ? err.message
124
- : err, tasks.map((task) => task[1]));
149
+ : err);
125
150
  }
126
151
  }
127
152
 
128
153
  const exampleQueue = new ExampleQueue();
129
154
 
130
- exampleQueue.runQueue('mysql_create:example:table_name');
155
+ exampleQueue.runQueue('ws');
131
156
  ```
132
157
 
133
158
  ## ⚖️ power-queues vs Existing Solutions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "power-queues",
3
- "version": "2.1.9",
3
+ "version": "2.1.10",
4
4
  "description": "High-performance Redis Streams queue for Node.js with Lua-powered bulk XADD, idempotent workers, heartbeat locks, stuck-task recovery, retries, DLQ, and distributed processing.",
5
5
  "author": "ihor-bielchenko",
6
6
  "license": "MIT",