@fgiova/sqs-consumer 3.2.0 → 3.2.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 +1 -2
- package/dist/cjs/index.js +29 -39
- package/dist/esm/index.d.mts +1 -2
- package/dist/esm/index.mjs +29 -39
- package/package.json +1 -1
package/dist/cjs/index.d.ts
CHANGED
|
@@ -46,9 +46,8 @@ export declare class SQSConsumer {
|
|
|
46
46
|
private readonly sqsClient;
|
|
47
47
|
private readonly hooks;
|
|
48
48
|
private readonly messageHandler;
|
|
49
|
-
private messagesOnFly;
|
|
50
49
|
private running;
|
|
51
|
-
private
|
|
50
|
+
private pollLoop;
|
|
52
51
|
private destroyed;
|
|
53
52
|
private readonly logger;
|
|
54
53
|
constructor(options: SQSConsumerOptions);
|
package/dist/cjs/index.js
CHANGED
|
@@ -17,9 +17,8 @@ var context_2 = require("./context");
|
|
|
17
17
|
Object.defineProperty(exports, "getAbortSignal", { enumerable: true, get: function () { return context_2.getAbortSignal; } });
|
|
18
18
|
class SQSConsumer {
|
|
19
19
|
constructor(options) {
|
|
20
|
-
this.messagesOnFly = 0;
|
|
21
20
|
this.running = false;
|
|
22
|
-
this.
|
|
21
|
+
this.pollLoop = null;
|
|
23
22
|
this.destroyed = false;
|
|
24
23
|
if (!options.queueARN)
|
|
25
24
|
throw new Error("queueARN is required");
|
|
@@ -96,7 +95,7 @@ class SQSConsumer {
|
|
|
96
95
|
const err = new errors_1.TimeoutError("Handler execution timed out");
|
|
97
96
|
abortController.abort(err);
|
|
98
97
|
reject(err);
|
|
99
|
-
}, this.handlerOptions.executionTimeout);
|
|
98
|
+
}, this.handlerOptions.executionTimeout).unref();
|
|
100
99
|
}),
|
|
101
100
|
]);
|
|
102
101
|
}
|
|
@@ -120,19 +119,17 @@ class SQSConsumer {
|
|
|
120
119
|
clearTimeout(timeoutId);
|
|
121
120
|
}
|
|
122
121
|
}
|
|
123
|
-
haExtendVisibilityTimeout(
|
|
124
|
-
if (this.handlerOptions.extendVisibilityTimeout !== false
|
|
125
|
-
|
|
126
|
-
// biome-ignore lint/style/noNonNullAssertion: ReceiptHandle must be present here
|
|
127
|
-
(message) => message.ReceiptHandle);
|
|
122
|
+
haExtendVisibilityTimeout(pendingReceipts, visibilityTimeout) {
|
|
123
|
+
if (this.handlerOptions.extendVisibilityTimeout !== false &&
|
|
124
|
+
visibilityTimeout > 0) {
|
|
128
125
|
return setInterval(async () => {
|
|
129
126
|
try {
|
|
130
|
-
await this.sqsClient.changeMessageVisibilityBatch(this.queueARN,
|
|
127
|
+
await this.sqsClient.changeMessageVisibilityBatch(this.queueARN, [...pendingReceipts], visibilityTimeout);
|
|
131
128
|
} /* c8 ignore next 3 */
|
|
132
129
|
catch (e) {
|
|
133
130
|
await this.hooks.runHook("onSQSError", e);
|
|
134
131
|
}
|
|
135
|
-
}, visibilityTimeout *
|
|
132
|
+
}, visibilityTimeout * 500);
|
|
136
133
|
}
|
|
137
134
|
return null;
|
|
138
135
|
}
|
|
@@ -160,7 +157,6 @@ class SQSConsumer {
|
|
|
160
157
|
let consecutiveErrors = 0;
|
|
161
158
|
while (this.running) {
|
|
162
159
|
try {
|
|
163
|
-
this.polling = true;
|
|
164
160
|
/* c8 ignore next 1 */
|
|
165
161
|
const visibilityTimeout = this.consumerOptions.visibilityTimeout ?? 30;
|
|
166
162
|
const messagesResult = await this.sqsClient.receiveMessage(this.queueARN, {
|
|
@@ -173,34 +169,27 @@ class SQSConsumer {
|
|
|
173
169
|
const messages = await this.hooks.runHook("onPoll",
|
|
174
170
|
/* c8 ignore next 1 */
|
|
175
171
|
messagesResult.Messages ?? []);
|
|
176
|
-
this.messagesOnFly += messages.length;
|
|
177
172
|
if (messages.length) {
|
|
178
|
-
const
|
|
173
|
+
const pendingReceipts = new Set(
|
|
174
|
+
// biome-ignore lint/style/noNonNullAssertion: ReceiptHandle must be present here
|
|
175
|
+
messages.map((message) => message.ReceiptHandle));
|
|
176
|
+
const haTimeout = this.haExtendVisibilityTimeout(pendingReceipts, visibilityTimeout);
|
|
179
177
|
try {
|
|
180
178
|
if (this.handlerOptions.parallelExecution !== false) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
await this.deleteMessages(results);
|
|
189
|
-
}
|
|
190
|
-
finally {
|
|
191
|
-
this.messagesOnFly -= messages.length;
|
|
192
|
-
}
|
|
179
|
+
const results = await (0, p_map_1.default)(messages, async (message) => {
|
|
180
|
+
return await this.runOnMessageHook(message);
|
|
181
|
+
}, {
|
|
182
|
+
concurrency: 10,
|
|
183
|
+
stopOnError: false,
|
|
184
|
+
});
|
|
185
|
+
await this.deleteMessages(results);
|
|
193
186
|
}
|
|
194
187
|
else {
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
finally {
|
|
202
|
-
this.messagesOnFly -= 1;
|
|
203
|
-
}
|
|
188
|
+
for (const message of messages) {
|
|
189
|
+
const result = await this.runOnMessageHook(message);
|
|
190
|
+
// biome-ignore lint/style/noNonNullAssertion: ReceiptHandle must be present here
|
|
191
|
+
pendingReceipts.delete(message.ReceiptHandle);
|
|
192
|
+
await this.deleteMessages([result]);
|
|
204
193
|
}
|
|
205
194
|
}
|
|
206
195
|
}
|
|
@@ -215,17 +204,20 @@ class SQSConsumer {
|
|
|
215
204
|
await this.hooks.runHook("onSQSError", e);
|
|
216
205
|
await (0, promises_1.setTimeout)(Math.min(1000 * 2 ** consecutiveErrors++, 30000));
|
|
217
206
|
}
|
|
218
|
-
this.polling = false;
|
|
219
207
|
}
|
|
220
208
|
}
|
|
221
209
|
async start() {
|
|
222
210
|
try {
|
|
223
211
|
if (this.running)
|
|
224
212
|
throw new Error("Consumer is already running");
|
|
213
|
+
if (this.pollLoop)
|
|
214
|
+
throw new Error("Consumer is stopping");
|
|
225
215
|
if (this.destroyed)
|
|
226
216
|
throw new Error("Consumer is destroyed");
|
|
227
217
|
this.running = true;
|
|
228
|
-
|
|
218
|
+
this.pollLoop = this.pollMessages().finally(() => {
|
|
219
|
+
this.pollLoop = null;
|
|
220
|
+
});
|
|
229
221
|
}
|
|
230
222
|
finally {
|
|
231
223
|
await this.hooks.runHook("onStart", this);
|
|
@@ -236,9 +228,7 @@ class SQSConsumer {
|
|
|
236
228
|
if (!this.running)
|
|
237
229
|
throw new Error("Consumer is not running");
|
|
238
230
|
this.running = false;
|
|
239
|
-
|
|
240
|
-
await (0, promises_1.setTimeout)(500);
|
|
241
|
-
}
|
|
231
|
+
await this.pollLoop;
|
|
242
232
|
if (destroy) {
|
|
243
233
|
await this.sqsClient.destroy(this.clientOptions.destroySigner);
|
|
244
234
|
this.destroyed = true;
|
package/dist/esm/index.d.mts
CHANGED
|
@@ -46,9 +46,8 @@ export declare class SQSConsumer {
|
|
|
46
46
|
private readonly sqsClient;
|
|
47
47
|
private readonly hooks;
|
|
48
48
|
private readonly messageHandler;
|
|
49
|
-
private messagesOnFly;
|
|
50
49
|
private running;
|
|
51
|
-
private
|
|
50
|
+
private pollLoop;
|
|
52
51
|
private destroyed;
|
|
53
52
|
private readonly logger;
|
|
54
53
|
constructor(options: SQSConsumerOptions);
|
package/dist/esm/index.mjs
CHANGED
|
@@ -10,9 +10,8 @@ import { Hooks } from "./hooks.mjs";
|
|
|
10
10
|
export { getAbortSignal } from "./context.mjs";
|
|
11
11
|
export class SQSConsumer {
|
|
12
12
|
constructor(options) {
|
|
13
|
-
this.messagesOnFly = 0;
|
|
14
13
|
this.running = false;
|
|
15
|
-
this.
|
|
14
|
+
this.pollLoop = null;
|
|
16
15
|
this.destroyed = false;
|
|
17
16
|
if (!options.queueARN)
|
|
18
17
|
throw new Error("queueARN is required");
|
|
@@ -89,7 +88,7 @@ export class SQSConsumer {
|
|
|
89
88
|
const err = new TimeoutError("Handler execution timed out");
|
|
90
89
|
abortController.abort(err);
|
|
91
90
|
reject(err);
|
|
92
|
-
}, this.handlerOptions.executionTimeout);
|
|
91
|
+
}, this.handlerOptions.executionTimeout).unref();
|
|
93
92
|
}),
|
|
94
93
|
]);
|
|
95
94
|
}
|
|
@@ -113,19 +112,17 @@ export class SQSConsumer {
|
|
|
113
112
|
clearTimeout(timeoutId);
|
|
114
113
|
}
|
|
115
114
|
}
|
|
116
|
-
haExtendVisibilityTimeout(
|
|
117
|
-
if (this.handlerOptions.extendVisibilityTimeout !== false
|
|
118
|
-
|
|
119
|
-
// biome-ignore lint/style/noNonNullAssertion: ReceiptHandle must be present here
|
|
120
|
-
(message) => message.ReceiptHandle);
|
|
115
|
+
haExtendVisibilityTimeout(pendingReceipts, visibilityTimeout) {
|
|
116
|
+
if (this.handlerOptions.extendVisibilityTimeout !== false &&
|
|
117
|
+
visibilityTimeout > 0) {
|
|
121
118
|
return setInterval(async () => {
|
|
122
119
|
try {
|
|
123
|
-
await this.sqsClient.changeMessageVisibilityBatch(this.queueARN,
|
|
120
|
+
await this.sqsClient.changeMessageVisibilityBatch(this.queueARN, [...pendingReceipts], visibilityTimeout);
|
|
124
121
|
} /* c8 ignore next 3 */
|
|
125
122
|
catch (e) {
|
|
126
123
|
await this.hooks.runHook("onSQSError", e);
|
|
127
124
|
}
|
|
128
|
-
}, visibilityTimeout *
|
|
125
|
+
}, visibilityTimeout * 500);
|
|
129
126
|
}
|
|
130
127
|
return null;
|
|
131
128
|
}
|
|
@@ -153,7 +150,6 @@ export class SQSConsumer {
|
|
|
153
150
|
let consecutiveErrors = 0;
|
|
154
151
|
while (this.running) {
|
|
155
152
|
try {
|
|
156
|
-
this.polling = true;
|
|
157
153
|
/* c8 ignore next 1 */
|
|
158
154
|
const visibilityTimeout = this.consumerOptions.visibilityTimeout ?? 30;
|
|
159
155
|
const messagesResult = await this.sqsClient.receiveMessage(this.queueARN, {
|
|
@@ -166,34 +162,27 @@ export class SQSConsumer {
|
|
|
166
162
|
const messages = await this.hooks.runHook("onPoll",
|
|
167
163
|
/* c8 ignore next 1 */
|
|
168
164
|
messagesResult.Messages ?? []);
|
|
169
|
-
this.messagesOnFly += messages.length;
|
|
170
165
|
if (messages.length) {
|
|
171
|
-
const
|
|
166
|
+
const pendingReceipts = new Set(
|
|
167
|
+
// biome-ignore lint/style/noNonNullAssertion: ReceiptHandle must be present here
|
|
168
|
+
messages.map((message) => message.ReceiptHandle));
|
|
169
|
+
const haTimeout = this.haExtendVisibilityTimeout(pendingReceipts, visibilityTimeout);
|
|
172
170
|
try {
|
|
173
171
|
if (this.handlerOptions.parallelExecution !== false) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
await this.deleteMessages(results);
|
|
182
|
-
}
|
|
183
|
-
finally {
|
|
184
|
-
this.messagesOnFly -= messages.length;
|
|
185
|
-
}
|
|
172
|
+
const results = await pMap(messages, async (message) => {
|
|
173
|
+
return await this.runOnMessageHook(message);
|
|
174
|
+
}, {
|
|
175
|
+
concurrency: 10,
|
|
176
|
+
stopOnError: false,
|
|
177
|
+
});
|
|
178
|
+
await this.deleteMessages(results);
|
|
186
179
|
}
|
|
187
180
|
else {
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
finally {
|
|
195
|
-
this.messagesOnFly -= 1;
|
|
196
|
-
}
|
|
181
|
+
for (const message of messages) {
|
|
182
|
+
const result = await this.runOnMessageHook(message);
|
|
183
|
+
// biome-ignore lint/style/noNonNullAssertion: ReceiptHandle must be present here
|
|
184
|
+
pendingReceipts.delete(message.ReceiptHandle);
|
|
185
|
+
await this.deleteMessages([result]);
|
|
197
186
|
}
|
|
198
187
|
}
|
|
199
188
|
}
|
|
@@ -208,17 +197,20 @@ export class SQSConsumer {
|
|
|
208
197
|
await this.hooks.runHook("onSQSError", e);
|
|
209
198
|
await setTimeoutAsync(Math.min(1000 * 2 ** consecutiveErrors++, 30000));
|
|
210
199
|
}
|
|
211
|
-
this.polling = false;
|
|
212
200
|
}
|
|
213
201
|
}
|
|
214
202
|
async start() {
|
|
215
203
|
try {
|
|
216
204
|
if (this.running)
|
|
217
205
|
throw new Error("Consumer is already running");
|
|
206
|
+
if (this.pollLoop)
|
|
207
|
+
throw new Error("Consumer is stopping");
|
|
218
208
|
if (this.destroyed)
|
|
219
209
|
throw new Error("Consumer is destroyed");
|
|
220
210
|
this.running = true;
|
|
221
|
-
|
|
211
|
+
this.pollLoop = this.pollMessages().finally(() => {
|
|
212
|
+
this.pollLoop = null;
|
|
213
|
+
});
|
|
222
214
|
}
|
|
223
215
|
finally {
|
|
224
216
|
await this.hooks.runHook("onStart", this);
|
|
@@ -229,9 +221,7 @@ export class SQSConsumer {
|
|
|
229
221
|
if (!this.running)
|
|
230
222
|
throw new Error("Consumer is not running");
|
|
231
223
|
this.running = false;
|
|
232
|
-
|
|
233
|
-
await setTimeoutAsync(500);
|
|
234
|
-
}
|
|
224
|
+
await this.pollLoop;
|
|
235
225
|
if (destroy) {
|
|
236
226
|
await this.sqsClient.destroy(this.clientOptions.destroySigner);
|
|
237
227
|
this.destroyed = true;
|