consumer-pgmq 1.0.2 → 1.0.4
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 +3 -5
- package/dist/consumer.js +97 -0
- package/dist/index.js +12 -0
- package/dist/queueDriver/PostgresQueueDriver.js +75 -0
- package/dist/queueDriver/SupabaseQueueDriver.js +47 -0
- package/dist/type.js +2 -0
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -54,9 +54,8 @@ if you use read consume type, the pool size is the number of messages will get a
|
|
|
54
54
|
import { config } from "dotenv"
|
|
55
55
|
config()
|
|
56
56
|
|
|
57
|
-
import Consumer from
|
|
57
|
+
import { SupabaseQueueDriver, Consumer } from "consumer-pgmq"
|
|
58
58
|
import { createClient, SupabaseClient } from '@supabase/supabase-js';
|
|
59
|
-
import SupabaseQueueDriver from '../src/queueDriver/SupabaseQueueDriver';
|
|
60
59
|
|
|
61
60
|
|
|
62
61
|
const supabase = createClient(
|
|
@@ -142,8 +141,7 @@ start()
|
|
|
142
141
|
import { config } from "dotenv"
|
|
143
142
|
config()
|
|
144
143
|
|
|
145
|
-
import Consumer from
|
|
146
|
-
import PostgresQueueDriver from '../src/queueDriver/PostgresQueueDriver';
|
|
144
|
+
import { Consumer, PostgresQueueDriver } from "consumer-pgmq"
|
|
147
145
|
import timersPromises from "node:timers/promises";
|
|
148
146
|
import knex from 'knex'
|
|
149
147
|
|
|
@@ -160,7 +158,7 @@ async function start() {
|
|
|
160
158
|
}
|
|
161
159
|
});
|
|
162
160
|
|
|
163
|
-
const postgresQueueDriver = new PostgresQueueDriver(connection)
|
|
161
|
+
const postgresQueueDriver = new PostgresQueueDriver(connection, "schema_name_here")
|
|
164
162
|
|
|
165
163
|
const consumer = new Consumer(
|
|
166
164
|
{
|
package/dist/consumer.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const events_1 = require("events");
|
|
4
|
+
const READ = "read";
|
|
5
|
+
/**
|
|
6
|
+
* The consumer class.
|
|
7
|
+
*/
|
|
8
|
+
class Consumer extends events_1.EventEmitter {
|
|
9
|
+
constructor(options, callback, client) {
|
|
10
|
+
super();
|
|
11
|
+
this.options = options;
|
|
12
|
+
this.callback = callback;
|
|
13
|
+
this.client = client;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get the message
|
|
17
|
+
* @returns Promise<{ data: Message[], error: any }>
|
|
18
|
+
* @private
|
|
19
|
+
*/
|
|
20
|
+
async getMessage() {
|
|
21
|
+
if (this.options.consumeType === READ) {
|
|
22
|
+
if (!this.options.visibilityTime) {
|
|
23
|
+
throw new Error("visibilityTime is required for read");
|
|
24
|
+
}
|
|
25
|
+
const { data, error } = await this.client.get(this.options.queueName, this.options.visibilityTime, this.options.poolSize || 1);
|
|
26
|
+
return { data: data, error };
|
|
27
|
+
}
|
|
28
|
+
const { data, error } = await this.client.pop(this.options.queueName);
|
|
29
|
+
return { data: data, error };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* @param data
|
|
33
|
+
* @returns Promise<void>
|
|
34
|
+
* @private
|
|
35
|
+
*/
|
|
36
|
+
async deleteMessage(data, signal) {
|
|
37
|
+
if (signal.aborted) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (this.options.consumeType === READ) {
|
|
41
|
+
const deleteMessage = await this.client.delete(this.options.queueName, data.msg_id);
|
|
42
|
+
if (deleteMessage.error) {
|
|
43
|
+
this.emit('error', deleteMessage.error);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Poll the message
|
|
50
|
+
* @returns Promise<void>
|
|
51
|
+
* @private
|
|
52
|
+
*/
|
|
53
|
+
async pollMessage() {
|
|
54
|
+
let promises = [];
|
|
55
|
+
try {
|
|
56
|
+
const { data, error } = await this.getMessage();
|
|
57
|
+
if (error) {
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
if (data.length === 0) {
|
|
61
|
+
setTimeout(() => this.pollMessage(), (this.options.timeMsWaitBeforeNextPolling || 1000) * 10);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const controller = new AbortController();
|
|
65
|
+
const signal = controller.signal;
|
|
66
|
+
for (let i = 0; i < (data.length || 1); i++) {
|
|
67
|
+
promises.push(this.callback(data[i].message, signal).then(async () => {
|
|
68
|
+
await this.deleteMessage(data[i], signal);
|
|
69
|
+
this.emit('finish', data[i]);
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
setTimeout(() => controller.abort(), (this.options.visibilityTime || 1) * 1000);
|
|
73
|
+
await Promise.all(promises);
|
|
74
|
+
promises = [];
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
if (err.name === "AbortError") {
|
|
78
|
+
this.emit("abort-error", err);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
this.emit('error', err);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
setTimeout(() => this.pollMessage(), this.options.timeMsWaitBeforeNextPolling || 1000);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Start the consumer
|
|
90
|
+
* @returns Promise<void>
|
|
91
|
+
* @public
|
|
92
|
+
*/
|
|
93
|
+
async start() {
|
|
94
|
+
await this.pollMessage();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
exports.default = Consumer;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SupabaseQueueDriver = exports.PostgresQueueDriver = exports.Consumer = void 0;
|
|
7
|
+
const consumer_1 = __importDefault(require("./consumer"));
|
|
8
|
+
exports.Consumer = consumer_1.default;
|
|
9
|
+
const PostgresQueueDriver_1 = __importDefault(require("./queueDriver/PostgresQueueDriver"));
|
|
10
|
+
exports.PostgresQueueDriver = PostgresQueueDriver_1.default;
|
|
11
|
+
const SupabaseQueueDriver_1 = __importDefault(require("./queueDriver/SupabaseQueueDriver"));
|
|
12
|
+
exports.SupabaseQueueDriver = SupabaseQueueDriver_1.default;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class PostgresQueueDriver {
|
|
4
|
+
constructor(connection, schema = "public") {
|
|
5
|
+
this.connection = connection;
|
|
6
|
+
this.schema = schema;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Get the message
|
|
10
|
+
* @param queueName The name of the queue
|
|
11
|
+
* @param visibilityTime The visibility time of the message
|
|
12
|
+
* @param totalMessages The total messages to get
|
|
13
|
+
* @returns Promise<{ data: Message[], error: any }>
|
|
14
|
+
*/
|
|
15
|
+
async get(queueName, visibilityTime, totalMessages) {
|
|
16
|
+
try {
|
|
17
|
+
const register = await this.connection.raw(`
|
|
18
|
+
SELECT * FROM ${this.schema}.read(
|
|
19
|
+
queue_name => ?,
|
|
20
|
+
vt => ?,
|
|
21
|
+
qty => ?
|
|
22
|
+
);
|
|
23
|
+
`, [queueName, visibilityTime, totalMessages]);
|
|
24
|
+
if (!register.rows) {
|
|
25
|
+
return { data: [], error: null };
|
|
26
|
+
}
|
|
27
|
+
return { data: register.rows, error: null };
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
return { data: [], error };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Pop the message
|
|
35
|
+
* @param queueName The name of the queue
|
|
36
|
+
* @returns Promise<{ data: Message[], error: any }>
|
|
37
|
+
*/
|
|
38
|
+
async pop(queueName) {
|
|
39
|
+
try {
|
|
40
|
+
const register = await this.connection.raw(`
|
|
41
|
+
SELECT * FROM ${this.schema}.pop(
|
|
42
|
+
queue_name => ?
|
|
43
|
+
);
|
|
44
|
+
`, [queueName]);
|
|
45
|
+
if (!register.rows) {
|
|
46
|
+
return { data: [], error: null };
|
|
47
|
+
}
|
|
48
|
+
return { data: register.rows, error: null };
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
return { data: [], error };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Delete the message
|
|
56
|
+
* @param queueName The name of the queue
|
|
57
|
+
* @param messageID The message ID
|
|
58
|
+
* @returns Promise<{ error: any }>
|
|
59
|
+
*/
|
|
60
|
+
async delete(queueName, messageID) {
|
|
61
|
+
try {
|
|
62
|
+
await this.connection.raw(`
|
|
63
|
+
SELECT * FROM ${this.schema}.delete(
|
|
64
|
+
queue_name => ?,
|
|
65
|
+
msg_id => ?
|
|
66
|
+
);
|
|
67
|
+
`, [queueName, messageID]);
|
|
68
|
+
return { error: null };
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
return { error };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.default = PostgresQueueDriver;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class SupabaseQueueDriver {
|
|
4
|
+
constructor(supabase) {
|
|
5
|
+
this.supabase = supabase;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Get the message
|
|
9
|
+
* @param queueName The name of the queue
|
|
10
|
+
* @param visibilityTime The visibility time of the message
|
|
11
|
+
* @param totalMessages The total messages to get
|
|
12
|
+
* @returns Promise<{ data: Message[], error: any }>
|
|
13
|
+
*/
|
|
14
|
+
async get(queueName, visibilityTime, totalMessages) {
|
|
15
|
+
const { data, error } = await this.supabase.rpc("read", {
|
|
16
|
+
queue_name: queueName,
|
|
17
|
+
sleep_seconds: visibilityTime,
|
|
18
|
+
n: totalMessages
|
|
19
|
+
});
|
|
20
|
+
return { data: data, error };
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Pop the message
|
|
24
|
+
* @param queueName The name of the queue
|
|
25
|
+
* @returns Promise<{ data: Message[], error: any }>
|
|
26
|
+
*/
|
|
27
|
+
async pop(queueName) {
|
|
28
|
+
const { data, error } = await this.supabase.rpc("pop", {
|
|
29
|
+
queue_name: queueName,
|
|
30
|
+
});
|
|
31
|
+
return { data: data, error };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Delete the message
|
|
35
|
+
* @param queueName The name of the queue
|
|
36
|
+
* @param messageID The message ID
|
|
37
|
+
* @returns Promise<{ error: any }>
|
|
38
|
+
*/
|
|
39
|
+
async delete(queueName, messageID) {
|
|
40
|
+
const { error } = await this.supabase.rpc("delete", {
|
|
41
|
+
queue_name: queueName,
|
|
42
|
+
message_id: messageID
|
|
43
|
+
});
|
|
44
|
+
return { error };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.default = SupabaseQueueDriver;
|
package/dist/type.js
ADDED
package/package.json
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "consumer-pgmq",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "The consumer of Supabase pgmq",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
8
9
|
"start:example:postgres": "ts-node ./examples/consumerPostgresDriver.ts",
|
|
9
10
|
"start:example:supabase": "ts-node ./examples/consumerSupabaseDriver.ts",
|
|
10
11
|
"start:dev": "ts-node-dev ./src/index.ts",
|
|
11
|
-
"test": "jest ./tests/*.spec.ts --detectOpenHandles"
|
|
12
|
+
"test": "jest ./tests/*.spec.ts --detectOpenHandles",
|
|
13
|
+
"prepublishOnly": "pnpm run build"
|
|
12
14
|
},
|
|
13
15
|
"keywords": [
|
|
14
16
|
"supabase",
|
|
@@ -30,5 +32,8 @@
|
|
|
30
32
|
"jest": "^30.1.1",
|
|
31
33
|
"knex": "^3.1.0",
|
|
32
34
|
"pg": "^8.16.3"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=20.0.0"
|
|
33
38
|
}
|
|
34
39
|
}
|