@fgiova/fastify-sqs-consumer 3.1.0 → 3.1.1
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/cjs/index.d.ts +8 -6
- package/dist/cjs/index.js +29 -49
- package/dist/esm/index.d.mts +8 -6
- package/dist/esm/index.mjs +29 -49
- package/package.json +2 -2
package/dist/cjs/index.d.ts
CHANGED
|
@@ -2,14 +2,16 @@ import { type Message, MiniSQSClient } from "@fgiova/mini-sqs-client";
|
|
|
2
2
|
import { type HooksOptions, SQSConsumer } from "@fgiova/sqs-consumer";
|
|
3
3
|
import type { FastifyInstance } from "fastify";
|
|
4
4
|
import type { Pool } from "undici";
|
|
5
|
+
type ConsumerEntry = {
|
|
6
|
+
consumer: SQSConsumer;
|
|
7
|
+
meta: {
|
|
8
|
+
pendingMessages: number;
|
|
9
|
+
};
|
|
10
|
+
ownedClient?: MiniSQSClient;
|
|
11
|
+
};
|
|
5
12
|
declare module "fastify" {
|
|
6
13
|
interface FastifyInstance {
|
|
7
|
-
sqsConsumers: Record<string,
|
|
8
|
-
consumer: SQSConsumer;
|
|
9
|
-
meta: {
|
|
10
|
-
pendingMessages: number;
|
|
11
|
-
};
|
|
12
|
-
}>;
|
|
14
|
+
sqsConsumers: Record<string, ConsumerEntry>;
|
|
13
15
|
}
|
|
14
16
|
}
|
|
15
17
|
declare function sqsConsumerPlugin(fastify: FastifyInstance, options: {
|
package/dist/cjs/index.js
CHANGED
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.fastifyPlugin = void 0;
|
|
7
7
|
const node_crypto_1 = require("node:crypto");
|
|
8
|
+
const promises_1 = require("node:timers/promises");
|
|
8
9
|
const mini_sqs_client_1 = require("@fgiova/mini-sqs-client");
|
|
9
10
|
const sqs_consumer_1 = require("@fgiova/sqs-consumer");
|
|
10
11
|
// @ts-expect-error
|
|
@@ -12,11 +13,13 @@ const unpromise_1 = require("@watchable/unpromise");
|
|
|
12
13
|
const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
|
|
13
14
|
function createConsumer(fastify, queueArn, handlerFunction, timeout = 90000, waitTimeSeconds = 20, batchSize = 1, attributeNames = [], messageAttributeNames = [], parallelExecution, hooks, sqs, credentials) {
|
|
14
15
|
const meta = { pendingMessages: 0 };
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
let ownedClient;
|
|
17
|
+
if (!(sqs instanceof mini_sqs_client_1.MiniSQSClient)) {
|
|
18
|
+
credentials = credentials ?? sqs?.credentials;
|
|
19
|
+
ownedClient = new mini_sqs_client_1.MiniSQSClient(queueArn.split(":")[3], sqs?.endpoint, sqs?.undiciOptions,
|
|
20
|
+
/* c8 ignore next 1 */
|
|
21
|
+
credentials ? { credentials } : undefined);
|
|
22
|
+
}
|
|
20
23
|
return {
|
|
21
24
|
consumer: new sqs_consumer_1.SQSConsumer({
|
|
22
25
|
queueARN: queueArn,
|
|
@@ -34,15 +37,7 @@ function createConsumer(fastify, queueArn, handlerFunction, timeout = 90000, wai
|
|
|
34
37
|
},
|
|
35
38
|
hooks,
|
|
36
39
|
clientOptions: {
|
|
37
|
-
sqsClient:
|
|
38
|
-
endpoint: typeof sqs === "object" && !(sqs instanceof mini_sqs_client_1.MiniSQSClient)
|
|
39
|
-
? sqs.endpoint
|
|
40
|
-
: undefined,
|
|
41
|
-
undiciOptions: typeof sqs === "object" && !(sqs instanceof mini_sqs_client_1.MiniSQSClient)
|
|
42
|
-
? sqs.undiciOptions
|
|
43
|
-
: undefined,
|
|
44
|
-
/* c8 ignore next 1 */
|
|
45
|
-
signer: credentials ? { credentials } : undefined,
|
|
40
|
+
sqsClient: ownedClient ?? sqs,
|
|
46
41
|
},
|
|
47
42
|
handler: async function handleMessageFunction(message) {
|
|
48
43
|
let timeoutId;
|
|
@@ -51,7 +46,7 @@ function createConsumer(fastify, queueArn, handlerFunction, timeout = 90000, wai
|
|
|
51
46
|
return await unpromise_1.Unpromise.race([
|
|
52
47
|
handlerFunction(message, fastify),
|
|
53
48
|
new Promise((_, reject) => {
|
|
54
|
-
timeoutId = setTimeout(() => reject(new Error("Handler execution timed out")), timeout + 1000);
|
|
49
|
+
timeoutId = setTimeout(() => reject(new Error("Handler execution timed out")), timeout + 1000).unref();
|
|
55
50
|
}),
|
|
56
51
|
]);
|
|
57
52
|
}
|
|
@@ -68,6 +63,7 @@ function createConsumer(fastify, queueArn, handlerFunction, timeout = 90000, wai
|
|
|
68
63
|
},
|
|
69
64
|
}),
|
|
70
65
|
meta,
|
|
66
|
+
ownedClient,
|
|
71
67
|
};
|
|
72
68
|
}
|
|
73
69
|
function sqsConsumerPlugin(fastify, options, done) {
|
|
@@ -88,48 +84,32 @@ function sqsConsumerPlugin(fastify, options, done) {
|
|
|
88
84
|
for (const consumerName of Object.keys(consumers)) {
|
|
89
85
|
consumers[consumerName].consumer.start().catch(async (e) => {
|
|
90
86
|
fastify.log.error(e);
|
|
91
|
-
|
|
92
|
-
.stop()
|
|
93
|
-
.catch((stopErr) => fastify.log.error(stopErr));
|
|
87
|
+
const { consumer, ownedClient } = consumers[consumerName];
|
|
94
88
|
delete consumers[consumerName];
|
|
89
|
+
await consumer.stop().catch((stopErr) => fastify.log.error(stopErr));
|
|
90
|
+
await ownedClient?.destroy().catch((err) => fastify.log.error(err));
|
|
95
91
|
});
|
|
96
92
|
}
|
|
97
93
|
done();
|
|
98
94
|
});
|
|
99
|
-
fastify.addHook("onClose", (
|
|
100
|
-
let allStopped = false;
|
|
95
|
+
fastify.addHook("onClose", async () => {
|
|
101
96
|
const arrayConsumers = Object.values(consumers);
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (Date.now()
|
|
97
|
+
const deadline = Date.now() + maxExecutionTimeout + 2000;
|
|
98
|
+
let stopped = false;
|
|
99
|
+
Promise.allSettled(arrayConsumers.map(({ consumer }) => consumer
|
|
100
|
+
.stop()
|
|
101
|
+
.catch((e) => fastify.log.error(`[fastify-sqs-consumer] Error stopping consumer: ${e}`)))).then(() => {
|
|
102
|
+
stopped = true;
|
|
103
|
+
});
|
|
104
|
+
while (!stopped ||
|
|
105
|
+
arrayConsumers.some(({ meta }) => meta.pendingMessages > 0)) {
|
|
106
|
+
if (Date.now() > deadline) {
|
|
112
107
|
fastify.log.warn("[fastify-sqs-consumer] Consumers are taking too long to stop... forcing shutdown");
|
|
113
|
-
|
|
114
|
-
return done();
|
|
115
|
-
}
|
|
116
|
-
/* c8 ignore next 5 */
|
|
117
|
-
if (isRunning) {
|
|
118
|
-
fastify.log.debug("[fastify-sqs-consumer] Some consumers still running... please wait");
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
|
-
else if (!allStopped) {
|
|
122
|
-
allStopped = true;
|
|
123
|
-
fastify.log.debug("[fastify-sqs-consumer] All consumers are stopped");
|
|
108
|
+
break;
|
|
124
109
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
fastify.log.debug(`[fastify-sqs-consumer] ${pendingMessages} pending messages`);
|
|
131
|
-
}
|
|
132
|
-
}, 500);
|
|
110
|
+
await (0, promises_1.setTimeout)(500);
|
|
111
|
+
}
|
|
112
|
+
await Promise.allSettled(arrayConsumers.map(({ ownedClient }) => ownedClient?.destroy()));
|
|
133
113
|
});
|
|
134
114
|
done();
|
|
135
115
|
}
|
package/dist/esm/index.d.mts
CHANGED
|
@@ -2,14 +2,16 @@ import { type Message, MiniSQSClient } from "@fgiova/mini-sqs-client";
|
|
|
2
2
|
import { type HooksOptions, SQSConsumer } from "@fgiova/sqs-consumer";
|
|
3
3
|
import type { FastifyInstance } from "fastify";
|
|
4
4
|
import type { Pool } from "undici";
|
|
5
|
+
type ConsumerEntry = {
|
|
6
|
+
consumer: SQSConsumer;
|
|
7
|
+
meta: {
|
|
8
|
+
pendingMessages: number;
|
|
9
|
+
};
|
|
10
|
+
ownedClient?: MiniSQSClient;
|
|
11
|
+
};
|
|
5
12
|
declare module "fastify" {
|
|
6
13
|
interface FastifyInstance {
|
|
7
|
-
sqsConsumers: Record<string,
|
|
8
|
-
consumer: SQSConsumer;
|
|
9
|
-
meta: {
|
|
10
|
-
pendingMessages: number;
|
|
11
|
-
};
|
|
12
|
-
}>;
|
|
14
|
+
sqsConsumers: Record<string, ConsumerEntry>;
|
|
13
15
|
}
|
|
14
16
|
}
|
|
15
17
|
declare function sqsConsumerPlugin(fastify: FastifyInstance, options: {
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
2
3
|
import { MiniSQSClient } from "@fgiova/mini-sqs-client";
|
|
3
4
|
import { SQSConsumer } from "@fgiova/sqs-consumer";
|
|
4
5
|
// @ts-expect-error
|
|
@@ -6,11 +7,13 @@ import { Unpromise } from "@watchable/unpromise";
|
|
|
6
7
|
import fp from "fastify-plugin";
|
|
7
8
|
function createConsumer(fastify, queueArn, handlerFunction, timeout = 90000, waitTimeSeconds = 20, batchSize = 1, attributeNames = [], messageAttributeNames = [], parallelExecution, hooks, sqs, credentials) {
|
|
8
9
|
const meta = { pendingMessages: 0 };
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
let ownedClient;
|
|
11
|
+
if (!(sqs instanceof MiniSQSClient)) {
|
|
12
|
+
credentials = credentials ?? sqs?.credentials;
|
|
13
|
+
ownedClient = new MiniSQSClient(queueArn.split(":")[3], sqs?.endpoint, sqs?.undiciOptions,
|
|
14
|
+
/* c8 ignore next 1 */
|
|
15
|
+
credentials ? { credentials } : undefined);
|
|
16
|
+
}
|
|
14
17
|
return {
|
|
15
18
|
consumer: new SQSConsumer({
|
|
16
19
|
queueARN: queueArn,
|
|
@@ -28,15 +31,7 @@ function createConsumer(fastify, queueArn, handlerFunction, timeout = 90000, wai
|
|
|
28
31
|
},
|
|
29
32
|
hooks,
|
|
30
33
|
clientOptions: {
|
|
31
|
-
sqsClient:
|
|
32
|
-
endpoint: typeof sqs === "object" && !(sqs instanceof MiniSQSClient)
|
|
33
|
-
? sqs.endpoint
|
|
34
|
-
: undefined,
|
|
35
|
-
undiciOptions: typeof sqs === "object" && !(sqs instanceof MiniSQSClient)
|
|
36
|
-
? sqs.undiciOptions
|
|
37
|
-
: undefined,
|
|
38
|
-
/* c8 ignore next 1 */
|
|
39
|
-
signer: credentials ? { credentials } : undefined,
|
|
34
|
+
sqsClient: ownedClient ?? sqs,
|
|
40
35
|
},
|
|
41
36
|
handler: async function handleMessageFunction(message) {
|
|
42
37
|
let timeoutId;
|
|
@@ -45,7 +40,7 @@ function createConsumer(fastify, queueArn, handlerFunction, timeout = 90000, wai
|
|
|
45
40
|
return await Unpromise.race([
|
|
46
41
|
handlerFunction(message, fastify),
|
|
47
42
|
new Promise((_, reject) => {
|
|
48
|
-
timeoutId = setTimeout(() => reject(new Error("Handler execution timed out")), timeout + 1000);
|
|
43
|
+
timeoutId = setTimeout(() => reject(new Error("Handler execution timed out")), timeout + 1000).unref();
|
|
49
44
|
}),
|
|
50
45
|
]);
|
|
51
46
|
}
|
|
@@ -62,6 +57,7 @@ function createConsumer(fastify, queueArn, handlerFunction, timeout = 90000, wai
|
|
|
62
57
|
},
|
|
63
58
|
}),
|
|
64
59
|
meta,
|
|
60
|
+
ownedClient,
|
|
65
61
|
};
|
|
66
62
|
}
|
|
67
63
|
function sqsConsumerPlugin(fastify, options, done) {
|
|
@@ -82,48 +78,32 @@ function sqsConsumerPlugin(fastify, options, done) {
|
|
|
82
78
|
for (const consumerName of Object.keys(consumers)) {
|
|
83
79
|
consumers[consumerName].consumer.start().catch(async (e) => {
|
|
84
80
|
fastify.log.error(e);
|
|
85
|
-
|
|
86
|
-
.stop()
|
|
87
|
-
.catch((stopErr) => fastify.log.error(stopErr));
|
|
81
|
+
const { consumer, ownedClient } = consumers[consumerName];
|
|
88
82
|
delete consumers[consumerName];
|
|
83
|
+
await consumer.stop().catch((stopErr) => fastify.log.error(stopErr));
|
|
84
|
+
await ownedClient?.destroy().catch((err) => fastify.log.error(err));
|
|
89
85
|
});
|
|
90
86
|
}
|
|
91
87
|
done();
|
|
92
88
|
});
|
|
93
|
-
fastify.addHook("onClose", (
|
|
94
|
-
let allStopped = false;
|
|
89
|
+
fastify.addHook("onClose", async () => {
|
|
95
90
|
const arrayConsumers = Object.values(consumers);
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (Date.now()
|
|
91
|
+
const deadline = Date.now() + maxExecutionTimeout + 2000;
|
|
92
|
+
let stopped = false;
|
|
93
|
+
Promise.allSettled(arrayConsumers.map(({ consumer }) => consumer
|
|
94
|
+
.stop()
|
|
95
|
+
.catch((e) => fastify.log.error(`[fastify-sqs-consumer] Error stopping consumer: ${e}`)))).then(() => {
|
|
96
|
+
stopped = true;
|
|
97
|
+
});
|
|
98
|
+
while (!stopped ||
|
|
99
|
+
arrayConsumers.some(({ meta }) => meta.pendingMessages > 0)) {
|
|
100
|
+
if (Date.now() > deadline) {
|
|
106
101
|
fastify.log.warn("[fastify-sqs-consumer] Consumers are taking too long to stop... forcing shutdown");
|
|
107
|
-
|
|
108
|
-
return done();
|
|
109
|
-
}
|
|
110
|
-
/* c8 ignore next 5 */
|
|
111
|
-
if (isRunning) {
|
|
112
|
-
fastify.log.debug("[fastify-sqs-consumer] Some consumers still running... please wait");
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
else if (!allStopped) {
|
|
116
|
-
allStopped = true;
|
|
117
|
-
fastify.log.debug("[fastify-sqs-consumer] All consumers are stopped");
|
|
102
|
+
break;
|
|
118
103
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
fastify.log.debug(`[fastify-sqs-consumer] ${pendingMessages} pending messages`);
|
|
125
|
-
}
|
|
126
|
-
}, 500);
|
|
104
|
+
await sleep(500);
|
|
105
|
+
}
|
|
106
|
+
await Promise.allSettled(arrayConsumers.map(({ ownedClient }) => ownedClient?.destroy()));
|
|
127
107
|
});
|
|
128
108
|
done();
|
|
129
109
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fgiova/fastify-sqs-consumer",
|
|
3
3
|
"description": "sqs-consumer fastify plugin",
|
|
4
|
-
"version": "3.1.
|
|
4
|
+
"version": "3.1.1",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"types": "./dist/cjs/index.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"test:debug": "tap --only --timeout=0",
|
|
30
30
|
"test:local": "TEST_LOCAL=true tap",
|
|
31
31
|
"test:local:debug": "TEST_LOCAL=true tap --only --timeout=0",
|
|
32
|
-
"test:coverage": "tap --coverage-report=lcovonly --coverage-report=text"
|
|
32
|
+
"test:coverage": "tap --timeout=90 --coverage-report=lcovonly --coverage-report=text"
|
|
33
33
|
},
|
|
34
34
|
"repository": {
|
|
35
35
|
"type": "git",
|