consumer-pgmq 3.1.0 → 3.3.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
@@ -55,6 +55,7 @@ if you use read consume type, the pool size is the number of messages will get a
55
55
  - Recommendation no set lower value to the option 'visibilityTime' if you are using the dead letter queue feature. For example: set visibilityTime value lower than 30 seconds, because if the message wasn't delete and the message be available again the consumer application can consume the message again.
56
56
  - On Postgresql queue driver when you enable the option 'isCustomQueueImplementation', means you created the custom table to work as queue. PS: in this case you need to use the **schema.sql** file to create a queue table, if you dont want jobs and jobs_dlq as table name you can change in the **schema.sql** file.
57
57
 
58
+
58
59
  ## Events
59
60
 
60
61
  - finish: When the message is consumed with success
@@ -1,11 +1,32 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ const pg_format_1 = __importDefault(require("pg-format"));
3
7
  class PostgresQueueDriver {
4
8
  constructor(connection, schema = "public", isCustomQueueImplementation = true) {
5
9
  this.connection = connection;
6
10
  this.schema = schema;
7
11
  this.isCustomQueueImplementation = isCustomQueueImplementation;
8
12
  }
13
+ /**
14
+ * Send the messages in batch
15
+ * @param queueName The name of the queue
16
+ * @param messages The message
17
+ * @returns Promise<{ error: any }>
18
+ */
19
+ async sendBatch(queueName, messages) {
20
+ try {
21
+ const items = messages.map((message) => [JSON.stringify(message)]);
22
+ const query = (0, pg_format_1.default)(`INSERT INTO ${this.schema}.${queueName}(payload) VALUES %L`, items);
23
+ await this.connection.query(query);
24
+ return { error: null };
25
+ }
26
+ catch (error) {
27
+ return { error };
28
+ }
29
+ }
9
30
  /**
10
31
  * Allocate the consumer
11
32
  * @returns Promise<{ id: string; }>
@@ -4,6 +4,13 @@ class SupabaseQueueDriver {
4
4
  constructor(supabase) {
5
5
  this.supabase = supabase;
6
6
  }
7
+ async sendBatch(queueName, messages) {
8
+ const { error } = await this.supabase.rpc("send_batch", {
9
+ queue_name: queueName,
10
+ messages: messages
11
+ });
12
+ return { error };
13
+ }
7
14
  /**
8
15
  * Send the message
9
16
  * @param queueName The name of the queue
@@ -42,30 +42,33 @@ async function start() {
42
42
  postgresQueueDriver
43
43
  );
44
44
 
45
+ const items: Array<{[key: string]: any }> = []
45
46
  for (let index = 0; index < 100; index++) {
46
- await postgresQueueDriver.send("jobs", {
47
+ items.push({
47
48
  message: `Message ${index}`,
48
49
  id: index
49
50
  })
50
51
  }
51
52
 
53
+ await postgresQueueDriver.sendBatch("jobs", items)
54
+
52
55
  console.log("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
53
56
 
54
- consumer.on("send-to-dlq", (message: { [key: string]: any }) => {
55
- console.log("Send to DLQ =>", message)
56
- })
57
+ // consumer.on("send-to-dlq", (message: { [key: string]: any }) => {
58
+ // console.log("Send to DLQ =>", message)
59
+ // })
57
60
 
58
- consumer.on('error', (err: Error) => {
59
- console.error('Error consuming message:', err.message);
60
- });
61
+ // consumer.on('error', (err: Error) => {
62
+ // console.error('Error consuming message:', err.message);
63
+ // });
61
64
 
62
- await consumer.start();
65
+ // await consumer.start();
63
66
 
64
- process.on("SIGINT", async () => {
65
- await consumer.freeConsumer()
66
- await pgClient.end()
67
- process.exit(0)
68
- })
67
+ // process.on("SIGINT", async () => {
68
+ // await consumer.freeConsumer()
69
+ // await pgClient.end()
70
+ // process.exit(0)
71
+ // })
69
72
 
70
73
  }
71
74
 
@@ -22,12 +22,16 @@ const supabaseQueueDriver = new SupabaseQueueDriver(
22
22
  )
23
23
 
24
24
  async function start() {
25
+ const items: Array<{ [key: string]: any; }> = []
25
26
  for (let i = 0; i < 50; i++) {
26
- await supabase.rpc("send", {
27
- queue_name: "subscriptions",
28
- message: { "message": `Message triggered at ${Date.now()}` }
29
- });
27
+ items.push({
28
+ message: `Message ${i}`,
29
+ id: i
30
+ })
30
31
  }
32
+
33
+ await supabaseQueueDriver.sendBatch("subscriptions", items)
34
+
31
35
  console.log("Total messages sent: ", 50)
32
36
 
33
37
  const consumer = new Consumer(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "consumer-pgmq",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "description": "The consumer of Supabase pgmq",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",
@@ -23,6 +23,7 @@
23
23
  "devDependencies": {
24
24
  "@types/jest": "^30.0.0",
25
25
  "@types/pg": "^8.15.5",
26
+ "@types/pg-format": "^1.0.5",
26
27
  "ts-jest": "^29.4.1",
27
28
  "ts-node": "^10.9.2",
28
29
  "ts-node-dev": "^2.0.0",
@@ -32,7 +33,8 @@
32
33
  "@supabase/supabase-js": "^2.56.0",
33
34
  "dotenv": "^17.2.1",
34
35
  "jest": "^30.1.1",
35
- "pg": "^8.16.3"
36
+ "pg": "^8.16.3",
37
+ "pg-format": "^1.0.4"
36
38
  },
37
39
  "engines": {
38
40
  "node": ">=20.0.0"
package/schema.sql CHANGED
@@ -1,3 +1,8 @@
1
+
2
+ CREATE TYPE job_status AS ENUM ('pending', 'in_progress');
3
+
4
+ CREATE TYPE worker_status AS ENUM ('idle', 'working');
5
+
1
6
  CREATE TABLE workers (
2
7
  id SERIAL PRIMARY KEY,
3
8
  status worker_status NOT NULL DEFAULT 'idle', -- Tracks the job lifecycle
@@ -45,6 +50,85 @@ CREATE INDEX ON public.workers (status);
45
50
 
46
51
  insert into workers(status)
47
52
  values ('idle'),
53
+ ('idle'),
54
+ ('idle'),
55
+ ('idle'),
56
+ ('idle'),
57
+ ('idle'),
58
+ ('idle'),
59
+ ('idle'),
60
+ ('idle'),
61
+ ('idle'),
62
+ ('idle'),
63
+ ('idle'),
64
+ ('idle'),
65
+ ('idle'),
66
+ ('idle'),
67
+ ('idle'),
68
+ ('idle'),
69
+ ('idle'),
70
+ ('idle'),
71
+ ('idle'),
72
+ ('idle'),
73
+ ('idle'),
74
+ ('idle'),
75
+ ('idle'),
76
+ ('idle'),
77
+ ('idle'),
78
+ ('idle'),
79
+ ('idle'),
80
+ ('idle'),
81
+ ('idle'),
82
+ ('idle'),
83
+ ('idle'),
84
+ ('idle'),
85
+ ('idle'),
86
+ ('idle'),
87
+ ('idle'),
88
+ ('idle'),
89
+ ('idle'),
90
+ ('idle'),
91
+ ('idle'),
92
+ ('idle'),
93
+ ('idle'),
94
+ ('idle'),
95
+ ('idle'),
96
+ ('idle'),
97
+ ('idle'),
98
+ ('idle'),
99
+ ('idle'),
100
+ ('idle'),
101
+ ('idle'),
102
+ ('idle'),
103
+ ('idle'),
104
+ ('idle'),
105
+ ('idle'),
106
+ ('idle'),
107
+ ('idle'),
108
+ ('idle'),
109
+ ('idle'),
110
+ ('idle'),
111
+ ('idle'),
112
+ ('idle'),
113
+ ('idle'),
114
+ ('idle'),
115
+ ('idle'),
116
+ ('idle'),
117
+ ('idle'),
118
+ ('idle'),
119
+ ('idle'),
120
+ ('idle'),
121
+ ('idle'),
122
+ ('idle'),
123
+ ('idle'),
124
+ ('idle'),
125
+ ('idle'),
126
+ ('idle'),
127
+ ('idle'),
128
+ ('idle'),
129
+ ('idle'),
130
+ ('idle'),
131
+ ('idle'),
48
132
  ('idle');
49
133
 
50
134
 
@@ -1,5 +1,6 @@
1
1
  import { Message, QueueDriver } from "../type";
2
2
  import { Client } from "pg";
3
+ import format from "pg-format"
3
4
 
4
5
  class PostgresQueueDriver implements QueueDriver {
5
6
 
@@ -10,6 +11,28 @@ class PostgresQueueDriver implements QueueDriver {
10
11
  private isCustomQueueImplementation = true
11
12
  ) { }
12
13
 
14
+
15
+ /**
16
+ * Send the messages in batch
17
+ * @param queueName The name of the queue
18
+ * @param messages The message
19
+ * @returns Promise<{ error: any }>
20
+ */
21
+ async sendBatch(
22
+ queueName: string,
23
+ messages: Array<{ [key: string]: any }>
24
+ ): Promise<{ error: any }> {
25
+ try {
26
+ const items = messages.map((message) => [JSON.stringify(message)]);
27
+ const query = format(`INSERT INTO ${this.schema}.${queueName}(payload) VALUES %L`, items);
28
+ await this.connection.query(query);
29
+
30
+ return { error: null };
31
+ } catch (error) {
32
+ return { error };
33
+ }
34
+ }
35
+
13
36
  /**
14
37
  * Allocate the consumer
15
38
  * @returns Promise<{ id: string; }>
@@ -7,6 +7,15 @@ class SupabaseQueueDriver implements QueueDriver {
7
7
  private supabase: SupabaseClient
8
8
  ) { }
9
9
 
10
+ async sendBatch(queueName: string, messages: Array<{ [key: string]: any; }>): Promise<{ error: any; }> {
11
+ const { error } = await this.supabase.rpc("send_batch", {
12
+ queue_name: queueName,
13
+ messages: messages
14
+ });
15
+
16
+ return { error };
17
+ }
18
+
10
19
  /**
11
20
  * Send the message
12
21
  * @param queueName The name of the queue
package/src/type.ts CHANGED
@@ -92,6 +92,18 @@ interface QueueDriver {
92
92
  signal: AbortSignal
93
93
  ): Promise<{ error: any }>;
94
94
 
95
+
96
+ /**
97
+ * Send the messages in batch
98
+ * @param queueName The name of the queue
99
+ * @param messages The message
100
+ * @returns Promise<{ error: any }>
101
+ */
102
+ sendBatch(
103
+ queueName: string,
104
+ messages: Array<{ [key: string]: any }>
105
+ ): Promise<{ error: any }>
106
+
95
107
  /**
96
108
  * Get the message
97
109
  * @param queueName The name of the queue