consumer-pgmq 2.0.1 → 3.1.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 +119 -22
- package/dist/consumer.js +43 -5
- package/dist/queueDriver/PostgresQueueDriver.js +144 -11
- package/dist/queueDriver/SupabaseQueueDriver.js +19 -0
- package/examples/consumerPostgresDriver.ts +42 -43
- package/examples/consumerSupabaseDriver.ts +15 -15
- package/package.json +3 -2
- package/schema.sql +50 -0
- package/src/consumer.ts +59 -6
- package/src/queueDriver/PostgresQueueDriver.ts +175 -14
- package/src/queueDriver/SupabaseQueueDriver.ts +23 -0
- package/src/type.ts +31 -0
- package/tests/consumer.spec.ts +201 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "consumer-pgmq",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "The consumer of Supabase pgmq",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
"packageManager": "pnpm@10.7.1",
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/jest": "^30.0.0",
|
|
25
|
+
"@types/pg": "^8.15.5",
|
|
25
26
|
"ts-jest": "^29.4.1",
|
|
27
|
+
"ts-node": "^10.9.2",
|
|
26
28
|
"ts-node-dev": "^2.0.0",
|
|
27
29
|
"typescript": "^5.9.2"
|
|
28
30
|
},
|
|
@@ -30,7 +32,6 @@
|
|
|
30
32
|
"@supabase/supabase-js": "^2.56.0",
|
|
31
33
|
"dotenv": "^17.2.1",
|
|
32
34
|
"jest": "^30.1.1",
|
|
33
|
-
"knex": "^3.1.0",
|
|
34
35
|
"pg": "^8.16.3"
|
|
35
36
|
},
|
|
36
37
|
"engines": {
|
package/schema.sql
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
CREATE TABLE workers (
|
|
2
|
+
id SERIAL PRIMARY KEY,
|
|
3
|
+
status worker_status NOT NULL DEFAULT 'idle', -- Tracks the job lifecycle
|
|
4
|
+
created_at TIMESTAMP DEFAULT now(),
|
|
5
|
+
updated_at TIMESTAMP DEFAULT now()
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
CREATE TABLE jobs (
|
|
9
|
+
id SERIAL PRIMARY KEY,
|
|
10
|
+
status job_status NOT NULL DEFAULT 'pending', -- Tracks the job lifecycle
|
|
11
|
+
payload JSONB, -- Chose payload as `jsonb` but could have gone with `bytea` instead.
|
|
12
|
+
visible_at TIMESTAMP DEFAULT now(), -- SQS visibility timeout (will come back to this later)
|
|
13
|
+
retry_count INT DEFAULT 0, -- Tracks retry attempts
|
|
14
|
+
created_at TIMESTAMP DEFAULT now(),
|
|
15
|
+
updated_at TIMESTAMP DEFAULT now()
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
CREATE TABLE jobs_dlq (
|
|
19
|
+
id SERIAL PRIMARY KEY,
|
|
20
|
+
status job_status NOT NULL DEFAULT 'pending', -- Tracks the job lifecycle
|
|
21
|
+
payload JSONB, -- Chose payload as `jsonb` but could have gone with `bytea` instead.
|
|
22
|
+
visible_at TIMESTAMP DEFAULT now(), -- SQS visibility timeout (will come back to this later)
|
|
23
|
+
retry_count INT DEFAULT 0, -- Tracks retry attempts
|
|
24
|
+
created_at TIMESTAMP DEFAULT now(),
|
|
25
|
+
updated_at TIMESTAMP DEFAULT now()
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
WITH next_workers AS (
|
|
30
|
+
SELECT id
|
|
31
|
+
FROM workers as w
|
|
32
|
+
WHERE
|
|
33
|
+
status = 'idle'
|
|
34
|
+
LIMIT 1
|
|
35
|
+
FOR UPDATE SKIP LOCKED
|
|
36
|
+
)
|
|
37
|
+
UPDATE workers
|
|
38
|
+
SET status = 'working',
|
|
39
|
+
updated_at = now()
|
|
40
|
+
FROM next_workers
|
|
41
|
+
WHERE workers.id = next_workers.id
|
|
42
|
+
RETURNING workers.*;
|
|
43
|
+
|
|
44
|
+
CREATE INDEX ON public.workers (status);
|
|
45
|
+
|
|
46
|
+
insert into workers(status)
|
|
47
|
+
values ('idle'),
|
|
48
|
+
('idle');
|
|
49
|
+
|
|
50
|
+
|
package/src/consumer.ts
CHANGED
|
@@ -22,6 +22,10 @@ class Consumer extends EventEmitter {
|
|
|
22
22
|
*/
|
|
23
23
|
private client: QueueDriver
|
|
24
24
|
|
|
25
|
+
private setTimeoutId: NodeJS.Timeout | null = null;
|
|
26
|
+
|
|
27
|
+
private id: string | null = null;
|
|
28
|
+
|
|
25
29
|
constructor(
|
|
26
30
|
options: Options,
|
|
27
31
|
callback: HandlerCallback,
|
|
@@ -31,6 +35,14 @@ class Consumer extends EventEmitter {
|
|
|
31
35
|
this.options = options;
|
|
32
36
|
this.callback = callback;
|
|
33
37
|
this.client = client;
|
|
38
|
+
this.valideOptions();
|
|
39
|
+
this.setTimeoutId = null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private valideOptions() {
|
|
43
|
+
if (this.options.queueNameDlq && !this.options.totalRetriesBeforeSendToDlq) {
|
|
44
|
+
throw new Error("The option totalRetriesBeforeSendToDlq is required when queueNameDlq is set");
|
|
45
|
+
}
|
|
34
46
|
}
|
|
35
47
|
|
|
36
48
|
/**
|
|
@@ -84,6 +96,9 @@ class Consumer extends EventEmitter {
|
|
|
84
96
|
* @private
|
|
85
97
|
*/
|
|
86
98
|
private async pollMessage() {
|
|
99
|
+
if (this.setTimeoutId) {
|
|
100
|
+
clearTimeout(this.setTimeoutId);
|
|
101
|
+
}
|
|
87
102
|
let promises: Promise<any>[] = [];
|
|
88
103
|
|
|
89
104
|
try {
|
|
@@ -93,18 +108,39 @@ class Consumer extends EventEmitter {
|
|
|
93
108
|
}
|
|
94
109
|
|
|
95
110
|
if (data.length === 0 && this.options.enabledPolling) {
|
|
96
|
-
setTimeout(
|
|
111
|
+
this.setTimeoutId = setTimeout(
|
|
97
112
|
() => this.pollMessage(),
|
|
98
113
|
(this.options.timeMsWaitBeforeNextPolling || 1000) * 10
|
|
99
114
|
);
|
|
100
115
|
return;
|
|
101
116
|
}
|
|
102
117
|
|
|
103
|
-
|
|
104
118
|
const controller = new AbortController();
|
|
105
119
|
const signal = controller.signal;
|
|
106
120
|
|
|
107
|
-
for (let i = 0; i <
|
|
121
|
+
for (let i = 0; i < data.length; i++) {
|
|
122
|
+
const hasSendToDlq = data[i] &&
|
|
123
|
+
this.options.queueNameDlq &&
|
|
124
|
+
this.options.totalRetriesBeforeSendToDlq &&
|
|
125
|
+
data[i].read_ct > this.options.totalRetriesBeforeSendToDlq
|
|
126
|
+
if (
|
|
127
|
+
hasSendToDlq
|
|
128
|
+
) {
|
|
129
|
+
promises.push(
|
|
130
|
+
this.client.send(
|
|
131
|
+
// @ts-ignore
|
|
132
|
+
this.options.queueNameDlq,
|
|
133
|
+
data[i].message,
|
|
134
|
+
signal
|
|
135
|
+
).then(async () => {
|
|
136
|
+
await this.deleteMessage(data[i], signal);
|
|
137
|
+
this.emit('send-to-dlq', data[i]);
|
|
138
|
+
})
|
|
139
|
+
)
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
108
144
|
promises.push(
|
|
109
145
|
this.callback(data[i].message, signal).then(async () => {
|
|
110
146
|
await this.deleteMessage(data[i], signal);
|
|
@@ -113,8 +149,12 @@ class Consumer extends EventEmitter {
|
|
|
113
149
|
);
|
|
114
150
|
}
|
|
115
151
|
|
|
116
|
-
setTimeout(() => controller.abort(), (this.options.visibilityTime || 1) * 1000);
|
|
117
|
-
|
|
152
|
+
const timeoutId = setTimeout(() => controller.abort(), (this.options.visibilityTime || 1) * 1000);
|
|
153
|
+
if (promises.length > 0) {
|
|
154
|
+
await Promise.allSettled(promises);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
clearTimeout(timeoutId);
|
|
118
158
|
promises = [];
|
|
119
159
|
} catch (err: any) {
|
|
120
160
|
if (err.name === "AbortError") {
|
|
@@ -126,7 +166,7 @@ class Consumer extends EventEmitter {
|
|
|
126
166
|
if (!this.options.enabledPolling) {
|
|
127
167
|
return;
|
|
128
168
|
}
|
|
129
|
-
setTimeout(() => this.pollMessage(), this.options.timeMsWaitBeforeNextPolling || 1000);
|
|
169
|
+
this.setTimeoutId = setTimeout(() => this.pollMessage(), this.options.timeMsWaitBeforeNextPolling || 1000);
|
|
130
170
|
}
|
|
131
171
|
}
|
|
132
172
|
|
|
@@ -136,8 +176,21 @@ class Consumer extends EventEmitter {
|
|
|
136
176
|
* @public
|
|
137
177
|
*/
|
|
138
178
|
async start() {
|
|
179
|
+
if (this.options.enableControlConsumer) {
|
|
180
|
+
const { id } = await this.client.allocateConsumer()
|
|
181
|
+
this.id = id
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
|
|
139
185
|
await this.pollMessage();
|
|
140
186
|
}
|
|
187
|
+
|
|
188
|
+
async freeConsumer() {
|
|
189
|
+
if (this.id) {
|
|
190
|
+
console.log("passed on here")
|
|
191
|
+
await this.client.freeConsumer(this.id)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
141
194
|
}
|
|
142
195
|
|
|
143
196
|
|
|
@@ -1,14 +1,152 @@
|
|
|
1
|
-
import { Knex } from "knex";
|
|
2
1
|
import { Message, QueueDriver } from "../type";
|
|
2
|
+
import { Client } from "pg";
|
|
3
3
|
|
|
4
4
|
class PostgresQueueDriver implements QueueDriver {
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
constructor(
|
|
8
|
-
private connection:
|
|
9
|
-
private schema: string = "public"
|
|
8
|
+
private connection: Client,
|
|
9
|
+
private schema: string = "public",
|
|
10
|
+
private isCustomQueueImplementation = true
|
|
10
11
|
) { }
|
|
11
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Allocate the consumer
|
|
15
|
+
* @returns Promise<{ id: string; }>
|
|
16
|
+
*/
|
|
17
|
+
async allocateConsumer(): Promise<{ id: string; }> {
|
|
18
|
+
const register = await this.connection.query(`
|
|
19
|
+
WITH next_workers AS (
|
|
20
|
+
SELECT id
|
|
21
|
+
FROM workers as w
|
|
22
|
+
WHERE
|
|
23
|
+
status = 'idle'
|
|
24
|
+
LIMIT 1
|
|
25
|
+
FOR UPDATE SKIP LOCKED
|
|
26
|
+
)
|
|
27
|
+
UPDATE workers
|
|
28
|
+
SET status = 'working',
|
|
29
|
+
updated_at = now()
|
|
30
|
+
FROM next_workers
|
|
31
|
+
WHERE workers.id = next_workers.id
|
|
32
|
+
RETURNING workers.*;
|
|
33
|
+
`)
|
|
34
|
+
|
|
35
|
+
if (register.rows.length == 0) {
|
|
36
|
+
throw new Error("No available consumer(worker) to allocate");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return { id: register.rows[0].id };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
async freeConsumer(id: string): Promise<void> {
|
|
44
|
+
try {
|
|
45
|
+
await this.connection.query(`UPDATE workers set status = 'idle' WHERE id = $1`, [id])
|
|
46
|
+
} catch (error) {
|
|
47
|
+
throw error
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
private async sendCustomQueue(
|
|
53
|
+
queueName: string,
|
|
54
|
+
message: { [key: string]: any; }
|
|
55
|
+
) {
|
|
56
|
+
try {
|
|
57
|
+
const query = `INSERT INTO ${this.schema}.${queueName}(payload) VALUES($1)`
|
|
58
|
+
await this.connection.query(query, [JSON.stringify(message)])
|
|
59
|
+
return { error: null };
|
|
60
|
+
} catch (error) {
|
|
61
|
+
return { error };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Send the message
|
|
67
|
+
* @param queueName The name of the queue
|
|
68
|
+
* @param message The message
|
|
69
|
+
* @returns Promise<{ error: any }>
|
|
70
|
+
*/
|
|
71
|
+
async send(
|
|
72
|
+
queueName: string,
|
|
73
|
+
message: { [key: string]: any; },
|
|
74
|
+
): Promise<{ error: any; }> {
|
|
75
|
+
if (this.isCustomQueueImplementation) {
|
|
76
|
+
return this.sendCustomQueue(queueName, message)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
await this.connection.query(`
|
|
81
|
+
SELECT * FROM ${this.schema}.send(
|
|
82
|
+
queue_name => $1,
|
|
83
|
+
msg => $2,
|
|
84
|
+
delay => $3
|
|
85
|
+
);
|
|
86
|
+
`, [queueName, message, 1]
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
return { error: null };
|
|
90
|
+
} catch (error) {
|
|
91
|
+
return { error };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private async getCustomQueue(
|
|
96
|
+
queueName: string,
|
|
97
|
+
visibilityTime: number,
|
|
98
|
+
totalMessages: number
|
|
99
|
+
): Promise<{ data: Message[]; error: any; }> {
|
|
100
|
+
try {
|
|
101
|
+
const register = await this.connection.query(
|
|
102
|
+
`
|
|
103
|
+
WITH next_job AS (
|
|
104
|
+
SELECT id
|
|
105
|
+
FROM ${queueName} as jobs
|
|
106
|
+
WHERE
|
|
107
|
+
(
|
|
108
|
+
status = 'pending'
|
|
109
|
+
OR (status = 'in_progress' AND visible_at <= now())
|
|
110
|
+
)
|
|
111
|
+
ORDER BY created_at
|
|
112
|
+
LIMIT $1
|
|
113
|
+
FOR UPDATE SKIP LOCKED
|
|
114
|
+
)
|
|
115
|
+
UPDATE jobs
|
|
116
|
+
SET status = 'in_progress',
|
|
117
|
+
updated_at = now(),
|
|
118
|
+
visible_at = now() + interval '${visibilityTime} seconds',
|
|
119
|
+
retry_count = retry_count + 1
|
|
120
|
+
FROM next_job
|
|
121
|
+
WHERE jobs.id = next_job.id
|
|
122
|
+
RETURNING jobs.*;
|
|
123
|
+
`,
|
|
124
|
+
[
|
|
125
|
+
totalMessages,
|
|
126
|
+
]
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
if (!register.rows) {
|
|
130
|
+
return { data: [], error: null };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const items: Message[] = [];
|
|
134
|
+
for (const row of register.rows) {
|
|
135
|
+
items.push({
|
|
136
|
+
msg_id: row.id,
|
|
137
|
+
read_ct: row.retry_count,
|
|
138
|
+
enqueued_at: row.created_at,
|
|
139
|
+
vt: row.visible_at,
|
|
140
|
+
message: row.payload, // Assuming the message content is stored in a column named 'payload' or '
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return { data: items, error: null };
|
|
145
|
+
} catch (error) {
|
|
146
|
+
return { data: [], error };
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
12
150
|
/**
|
|
13
151
|
* Get the message
|
|
14
152
|
* @param queueName The name of the queue
|
|
@@ -17,12 +155,16 @@ class PostgresQueueDriver implements QueueDriver {
|
|
|
17
155
|
* @returns Promise<{ data: Message[], error: any }>
|
|
18
156
|
*/
|
|
19
157
|
async get(queueName: string, visibilityTime: number, totalMessages: number): Promise<{ data: Message[]; error: any; }> {
|
|
158
|
+
if (this.isCustomQueueImplementation) {
|
|
159
|
+
return this.getCustomQueue(queueName, visibilityTime, totalMessages);
|
|
160
|
+
}
|
|
161
|
+
|
|
20
162
|
try {
|
|
21
|
-
const register = await this.connection.
|
|
163
|
+
const register = await this.connection.query(`
|
|
22
164
|
SELECT * FROM ${this.schema}.read(
|
|
23
|
-
queue_name =>
|
|
24
|
-
vt =>
|
|
25
|
-
qty =>
|
|
165
|
+
queue_name => $1,
|
|
166
|
+
vt => $2,
|
|
167
|
+
qty => $3
|
|
26
168
|
);
|
|
27
169
|
`, [queueName, visibilityTime, totalMessages]
|
|
28
170
|
)
|
|
@@ -44,11 +186,18 @@ class PostgresQueueDriver implements QueueDriver {
|
|
|
44
186
|
* @returns Promise<{ data: Message[], error: any }>
|
|
45
187
|
*/
|
|
46
188
|
async pop(queueName: string): Promise<{ data: Message[]; error: any; }> {
|
|
189
|
+
if (this.isCustomQueueImplementation) {
|
|
190
|
+
const result = await this.getCustomQueue(queueName, 30, 1);
|
|
191
|
+
if (result.data && result.data[0]) {
|
|
192
|
+
await this.delete(queueName, result.data[0].msg_id);
|
|
193
|
+
}
|
|
194
|
+
return result
|
|
195
|
+
}
|
|
47
196
|
try {
|
|
48
|
-
const register = await this.connection.
|
|
197
|
+
const register = await this.connection.query(`
|
|
49
198
|
SELECT * FROM ${this.schema}.pop(
|
|
50
|
-
queue_name =>
|
|
51
|
-
)
|
|
199
|
+
queue_name => $1
|
|
200
|
+
)
|
|
52
201
|
`, [queueName]
|
|
53
202
|
)
|
|
54
203
|
|
|
@@ -63,6 +212,14 @@ class PostgresQueueDriver implements QueueDriver {
|
|
|
63
212
|
|
|
64
213
|
}
|
|
65
214
|
|
|
215
|
+
private async deleteCustomQueue(queueName: string, messageID: number) {
|
|
216
|
+
await this.connection.query(`
|
|
217
|
+
DELETE FROM ${queueName}
|
|
218
|
+
WHERE id = $1;`, [messageID]
|
|
219
|
+
)
|
|
220
|
+
return { error: null };
|
|
221
|
+
}
|
|
222
|
+
|
|
66
223
|
/**
|
|
67
224
|
* Delete the message
|
|
68
225
|
* @param queueName The name of the queue
|
|
@@ -71,12 +228,16 @@ class PostgresQueueDriver implements QueueDriver {
|
|
|
71
228
|
*/
|
|
72
229
|
async delete(queueName: string, messageID: number): Promise<{ error: any; }> {
|
|
73
230
|
try {
|
|
74
|
-
|
|
231
|
+
if (this.isCustomQueueImplementation) {
|
|
232
|
+
return this.deleteCustomQueue(queueName, messageID)
|
|
233
|
+
}
|
|
234
|
+
await this.connection.query(`
|
|
75
235
|
SELECT * FROM ${this.schema}.delete(
|
|
76
|
-
queue_name =>
|
|
77
|
-
msg_id =>
|
|
236
|
+
queue_name => $1,
|
|
237
|
+
msg_id => $2
|
|
78
238
|
);
|
|
79
|
-
`, [queueName, messageID]
|
|
239
|
+
`, [queueName, messageID],
|
|
240
|
+
|
|
80
241
|
)
|
|
81
242
|
|
|
82
243
|
return { error: null };
|
|
@@ -7,6 +7,21 @@ class SupabaseQueueDriver implements QueueDriver {
|
|
|
7
7
|
private supabase: SupabaseClient
|
|
8
8
|
) { }
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Send the message
|
|
12
|
+
* @param queueName The name of the queue
|
|
13
|
+
* @param message The message
|
|
14
|
+
* @returns Promise<{ error: any }>
|
|
15
|
+
*/
|
|
16
|
+
async send(queueName: string, message: { [key: string]: any; }): Promise<{ error: any; }> {
|
|
17
|
+
const { error } = await this.supabase.rpc("send", {
|
|
18
|
+
queue_name: queueName,
|
|
19
|
+
message: message
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return { error };
|
|
23
|
+
}
|
|
24
|
+
|
|
10
25
|
/**
|
|
11
26
|
* Get the message
|
|
12
27
|
* @param queueName The name of the queue
|
|
@@ -52,6 +67,14 @@ class SupabaseQueueDriver implements QueueDriver {
|
|
|
52
67
|
return { error };
|
|
53
68
|
}
|
|
54
69
|
|
|
70
|
+
allocateConsumer(): Promise<{ id: string; }> {
|
|
71
|
+
throw new Error("method logic no implemented")
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
freeConsumer(id: string): Promise<void> {
|
|
75
|
+
throw new Error("method logic no implemented")
|
|
76
|
+
}
|
|
77
|
+
|
|
55
78
|
}
|
|
56
79
|
|
|
57
80
|
export default SupabaseQueueDriver;
|
package/src/type.ts
CHANGED
|
@@ -30,6 +30,21 @@ interface Options {
|
|
|
30
30
|
* The enabled polling. PS: if true, the consumer will poll the message
|
|
31
31
|
*/
|
|
32
32
|
enabledPolling: boolean;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The name of the queue DLQ
|
|
36
|
+
*/
|
|
37
|
+
queueNameDlq?: string;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The total retries before send the message to DLQ. PS: if set queueNameDlq, this option is required
|
|
41
|
+
*/
|
|
42
|
+
totalRetriesBeforeSendToDlq?: number;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The enable control consumer. PS: if true, set the allocate a consumer from table workers, because that way you can control the number of consumers(workers)
|
|
46
|
+
*/
|
|
47
|
+
enableControlConsumer?: boolean;
|
|
33
48
|
}
|
|
34
49
|
|
|
35
50
|
/**
|
|
@@ -65,6 +80,18 @@ interface Message {
|
|
|
65
80
|
|
|
66
81
|
interface QueueDriver {
|
|
67
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Send the message
|
|
85
|
+
* @param queueName The name of the queue
|
|
86
|
+
* @param message The message
|
|
87
|
+
* @returns Promise<{ error: any }>
|
|
88
|
+
*/
|
|
89
|
+
send(
|
|
90
|
+
queueName: string,
|
|
91
|
+
message: { [key: string]: any },
|
|
92
|
+
signal: AbortSignal
|
|
93
|
+
): Promise<{ error: any }>;
|
|
94
|
+
|
|
68
95
|
/**
|
|
69
96
|
* Get the message
|
|
70
97
|
* @param queueName The name of the queue
|
|
@@ -97,6 +124,10 @@ interface QueueDriver {
|
|
|
97
124
|
queueName: string,
|
|
98
125
|
messageID: number
|
|
99
126
|
): Promise<{ error: any }>;
|
|
127
|
+
|
|
128
|
+
allocateConsumer(): Promise<{ id: string }>;
|
|
129
|
+
|
|
130
|
+
freeConsumer(id: string): Promise<void>;
|
|
100
131
|
}
|
|
101
132
|
|
|
102
133
|
export type { Options, HandlerCallback, Message, QueueDriver }
|