consumer-pgmq 1.0.1 → 1.0.3
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/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 +4 -2
- package/src/index.ts +3 -1
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.3",
|
|
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",
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import Consumer from './consumer';
|
|
2
|
+
import PostgresQueueDriver from './queueDriver/PostgresQueueDriver';
|
|
3
|
+
import SupabaseQueueDriver from './queueDriver/SupabaseQueueDriver';
|
|
2
4
|
|
|
3
|
-
export
|
|
5
|
+
export { Consumer, PostgresQueueDriver, SupabaseQueueDriver };
|