sqs-consumer 6.2.1 → 7.0.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.
@@ -14,7 +14,7 @@ jobs:
14
14
  runs-on: ubuntu-latest
15
15
  strategy:
16
16
  matrix:
17
- node-version: [14.x]
17
+ node-version: [18.x]
18
18
 
19
19
  steps:
20
20
  - uses: actions/checkout@v3
@@ -0,0 +1,17 @@
1
+ name: Add bugs to bugs project
2
+
3
+ on:
4
+ issues:
5
+ types:
6
+ - opened
7
+ - labeled
8
+
9
+ jobs:
10
+ add-to-project:
11
+ name: Add issue to project
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/add-to-project@v0.4.0
15
+ with:
16
+ project-url: https://github.com/orgs/bbc/projects/170
17
+ github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
@@ -14,7 +14,7 @@ jobs:
14
14
  runs-on: ubuntu-latest
15
15
  strategy:
16
16
  matrix:
17
- node-version: [14.x, 16.x, 18.x]
17
+ node-version: [16.x, 18.x]
18
18
 
19
19
  steps:
20
20
  - uses: actions/checkout@v3
package/README.md CHANGED
@@ -22,6 +22,12 @@ npm install --save-dev sqs-consumer
22
22
  > npm install sqs-consumer@5.8.0 --save-dev
23
23
  > ```
24
24
 
25
+ ### Node version
26
+
27
+ From v7 and above, this library will only support Node v16 or above. If you are still using Node 14, please use a previous version of the library.
28
+
29
+ This decision was made due to the removal of security support from the Node.JS team from April 30th, 2023.
30
+
25
31
  ## Usage
26
32
 
27
33
  ```js
@@ -49,6 +55,7 @@ app.start();
49
55
  - Messages are deleted from the queue once the handler function has completed successfully.
50
56
  - Throwing an error (or returning a rejected promise) from the handler function will cause the message to be left on the queue. An [SQS redrive policy](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/SQSDeadLetterQueue.html) can be used to move messages that cannot be processed to a dead letter queue.
51
57
  - By default messages are processed one at a time – a new message won't be received until the first one has been processed. To process messages in parallel, use the `batchSize` option [detailed below](#options).
58
+ - By default, messages that are sent to the `handleMessage` and `handleMessageBatch` functions will be considered as processed if they return without an error. To acknowledge individual messages, please return the message that you want to acknowledge if you are using `handleMessage` or the messages for `handleMessageBatch`. It's also important to await any processing that you are doing to ensure that messages are processed one at a time.
52
59
 
53
60
  ### Credentials
54
61
 
@@ -108,9 +115,13 @@ Creates a new SQS consumer using the [defined options](https://bbc.github.io/sqs
108
115
 
109
116
  Start polling the queue for messages.
110
117
 
111
- ### `consumer.stop()`
118
+ ### `consumer.stop(options)`
119
+
120
+ Stop polling the queue for messages. [You can find the options definition here](https://bbc.github.io/sqs-consumer/interfaces/StopOptions.html).
121
+
122
+ By default, the value of `abort` is set to `false` which means pre existing requests to AWS SQS will still be made until they have concluded. If you would like to abort these requests instead, pass the abort value as `true`, like so:
112
123
 
113
- Stop polling the queue for messages (pre existing requests will still be made until concluded).
124
+ `consumer.stop({ abort: true })`
114
125
 
115
126
  ### `consumer.isRunning`
116
127
 
@@ -1,4 +1,4 @@
1
- import { ConsumerOptions, TypedEventEmitter } from './types';
1
+ import { ConsumerOptions, TypedEventEmitter, StopOptions } from './types';
2
2
  /**
3
3
  * [Usage](https://bbc.github.io/sqs-consumer/index.html#usage)
4
4
  */
@@ -34,7 +34,7 @@ export declare class Consumer extends TypedEventEmitter {
34
34
  /**
35
35
  * Stop polling the queue for messages (pre existing requests will still be made until concluded).
36
36
  */
37
- stop(): void;
37
+ stop(options: StopOptions): void;
38
38
  /**
39
39
  * Returns the current polling state of the consumer: `true` if it is actively polling, `false` if it is not.
40
40
  */
@@ -45,6 +45,10 @@ export declare class Consumer extends TypedEventEmitter {
45
45
  * @param message The message that the error occurred on
46
46
  */
47
47
  private emitError;
48
+ /**
49
+ * A reusable options object for sqs.send that's used to avoid duplication.
50
+ */
51
+ private sqsSendOptions;
48
52
  /**
49
53
  * Poll for new messages from SQS
50
54
  */
package/dist/consumer.js CHANGED
@@ -7,6 +7,7 @@ const types_1 = require("./types");
7
7
  const bind_1 = require("./bind");
8
8
  const errors_1 = require("./errors");
9
9
  const validation_1 = require("./validation");
10
+ const controllers_1 = require("./controllers");
10
11
  const debug = (0, debug_1.default)('sqs-consumer');
11
12
  /**
12
13
  * [Usage](https://bbc.github.io/sqs-consumer/index.html#usage)
@@ -19,6 +20,12 @@ class Consumer extends types_1.TypedEventEmitter {
19
20
  this.heartbeatTimeoutId = undefined;
20
21
  this.handleMessageTimeoutId = undefined;
21
22
  this.stopped = true;
23
+ /**
24
+ * A reusable options object for sqs.send that's used to avoid duplication.
25
+ */
26
+ this.sqsSendOptions = {
27
+ abortSignal: controllers_1.abortController.signal
28
+ };
22
29
  (0, validation_1.assertOptions)(options);
23
30
  this.queueUrl = options.queueUrl;
24
31
  this.handleMessage = options.handleMessage;
@@ -62,7 +69,7 @@ class Consumer extends types_1.TypedEventEmitter {
62
69
  /**
63
70
  * Stop polling the queue for messages (pre existing requests will still be made until concluded).
64
71
  */
65
- stop() {
72
+ stop(options) {
66
73
  if (this.stopped) {
67
74
  debug('Consumer was already stopped');
68
75
  return;
@@ -73,6 +80,11 @@ class Consumer extends types_1.TypedEventEmitter {
73
80
  clearTimeout(this.pollingTimeoutId);
74
81
  this.pollingTimeoutId = undefined;
75
82
  }
83
+ if (options === null || options === void 0 ? void 0 : options.abort) {
84
+ debug('Aborting SQS requests');
85
+ controllers_1.abortController.abort();
86
+ this.emit('aborted');
87
+ }
76
88
  this.emit('stopped');
77
89
  }
78
90
  /**
@@ -143,7 +155,7 @@ class Consumer extends types_1.TypedEventEmitter {
143
155
  */
144
156
  async receiveMessage(params) {
145
157
  try {
146
- return await this.sqs.send(new client_sqs_1.ReceiveMessageCommand(params));
158
+ return await this.sqs.send(new client_sqs_1.ReceiveMessageCommand(params), this.sqsSendOptions);
147
159
  }
148
160
  catch (err) {
149
161
  throw (0, errors_1.toSQSError)(err, `SQS receive message failed: ${err.message}`);
@@ -253,7 +265,7 @@ class Consumer extends types_1.TypedEventEmitter {
253
265
  ReceiptHandle: message.ReceiptHandle,
254
266
  VisibilityTimeout: timeout
255
267
  };
256
- return await this.sqs.send(new client_sqs_1.ChangeMessageVisibilityCommand(input));
268
+ return await this.sqs.send(new client_sqs_1.ChangeMessageVisibilityCommand(input), this.sqsSendOptions);
257
269
  }
258
270
  catch (err) {
259
271
  this.emit('error', (0, errors_1.toSQSError)(err, `Error changing visibility timeout: ${err.message}`), message);
@@ -274,7 +286,7 @@ class Consumer extends types_1.TypedEventEmitter {
274
286
  }))
275
287
  };
276
288
  try {
277
- return await this.sqs.send(new client_sqs_1.ChangeMessageVisibilityBatchCommand(params));
289
+ return await this.sqs.send(new client_sqs_1.ChangeMessageVisibilityBatchCommand(params), this.sqsSendOptions);
278
290
  }
279
291
  catch (err) {
280
292
  this.emit('error', (0, errors_1.toSQSError)(err, `Error changing visibility timeout: ${err.message}`), messages);
@@ -342,7 +354,7 @@ class Consumer extends types_1.TypedEventEmitter {
342
354
  ReceiptHandle: message.ReceiptHandle
343
355
  };
344
356
  try {
345
- await this.sqs.send(new client_sqs_1.DeleteMessageCommand(deleteParams));
357
+ await this.sqs.send(new client_sqs_1.DeleteMessageCommand(deleteParams), this.sqsSendOptions);
346
358
  }
347
359
  catch (err) {
348
360
  throw (0, errors_1.toSQSError)(err, `SQS delete message failed: ${err.message}`);
@@ -366,7 +378,7 @@ class Consumer extends types_1.TypedEventEmitter {
366
378
  }))
367
379
  };
368
380
  try {
369
- await this.sqs.send(new client_sqs_1.DeleteMessageBatchCommand(deleteParams));
381
+ await this.sqs.send(new client_sqs_1.DeleteMessageBatchCommand(deleteParams), this.sqsSendOptions);
370
382
  }
371
383
  catch (err) {
372
384
  throw (0, errors_1.toSQSError)(err, `SQS delete message failed: ${err.message}`);
@@ -0,0 +1 @@
1
+ export declare const abortController: AbortController;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.abortController = void 0;
4
+ exports.abortController = new AbortController();
package/dist/types.d.ts CHANGED
@@ -105,6 +105,14 @@ export interface ConsumerOptions {
105
105
  */
106
106
  handleMessageBatch?(messages: Message[]): Promise<Message[] | void>;
107
107
  }
108
+ export interface StopOptions {
109
+ /**
110
+ * Default to `false`, if you want the stop action to also abort requests to SQS
111
+ * set this to `true`.
112
+ * @defaultvalue `false`
113
+ */
114
+ abort?: boolean;
115
+ }
108
116
  export interface Events {
109
117
  /**
110
118
  * Fired after one batch of items (up to `batchSize`) has been successfully processed.
@@ -137,6 +145,10 @@ export interface Events {
137
145
  * Fired when an error occurs processing the message.
138
146
  */
139
147
  processing_error: [Error, Message];
148
+ /**
149
+ * Fired when requests to SQS were aborted.
150
+ */
151
+ aborted: [];
140
152
  /**
141
153
  * Fired when the consumer finally stops its work.
142
154
  */
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "sqs-consumer",
3
- "version": "6.2.1",
3
+ "version": "7.0.1",
4
4
  "description": "Build SQS-based Node applications without the boilerplate",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
+ "engines": {
8
+ "node": ">=16.0.0"
9
+ },
7
10
  "scripts": {
8
11
  "build": "npm run clean && tsc",
9
12
  "watch": "tsc --watch",
package/src/consumer.ts CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  } from '@aws-sdk/client-sqs';
18
18
  import Debug from 'debug';
19
19
 
20
- import { ConsumerOptions, TypedEventEmitter } from './types';
20
+ import { ConsumerOptions, TypedEventEmitter, StopOptions } from './types';
21
21
  import { autoBind } from './bind';
22
22
  import {
23
23
  SQSError,
@@ -26,6 +26,7 @@ import {
26
26
  isConnectionError
27
27
  } from './errors';
28
28
  import { assertOptions, hasMessages } from './validation';
29
+ import { abortController } from './controllers';
29
30
 
30
31
  const debug = Debug('sqs-consumer');
31
32
 
@@ -101,7 +102,7 @@ export class Consumer extends TypedEventEmitter {
101
102
  /**
102
103
  * Stop polling the queue for messages (pre existing requests will still be made until concluded).
103
104
  */
104
- public stop(): void {
105
+ public stop(options: StopOptions): void {
105
106
  if (this.stopped) {
106
107
  debug('Consumer was already stopped');
107
108
  return;
@@ -115,6 +116,14 @@ export class Consumer extends TypedEventEmitter {
115
116
  this.pollingTimeoutId = undefined;
116
117
  }
117
118
 
119
+ if (options?.abort) {
120
+ debug('Aborting SQS requests');
121
+
122
+ abortController.abort();
123
+
124
+ this.emit('aborted');
125
+ }
126
+
118
127
  this.emit('stopped');
119
128
  }
120
129
 
@@ -142,6 +151,13 @@ export class Consumer extends TypedEventEmitter {
142
151
  }
143
152
  }
144
153
 
154
+ /**
155
+ * A reusable options object for sqs.send that's used to avoid duplication.
156
+ */
157
+ private sqsSendOptions = {
158
+ abortSignal: abortController.signal
159
+ };
160
+
145
161
  /**
146
162
  * Poll for new messages from SQS
147
163
  */
@@ -190,7 +206,10 @@ export class Consumer extends TypedEventEmitter {
190
206
  params: ReceiveMessageCommandInput
191
207
  ): Promise<ReceiveMessageCommandOutput> {
192
208
  try {
193
- return await this.sqs.send(new ReceiveMessageCommand(params));
209
+ return await this.sqs.send(
210
+ new ReceiveMessageCommand(params),
211
+ this.sqsSendOptions
212
+ );
194
213
  } catch (err) {
195
214
  throw toSQSError(err, `SQS receive message failed: ${err.message}`);
196
215
  }
@@ -319,7 +338,10 @@ export class Consumer extends TypedEventEmitter {
319
338
  ReceiptHandle: message.ReceiptHandle,
320
339
  VisibilityTimeout: timeout
321
340
  };
322
- return await this.sqs.send(new ChangeMessageVisibilityCommand(input));
341
+ return await this.sqs.send(
342
+ new ChangeMessageVisibilityCommand(input),
343
+ this.sqsSendOptions
344
+ );
323
345
  } catch (err) {
324
346
  this.emit(
325
347
  'error',
@@ -348,7 +370,8 @@ export class Consumer extends TypedEventEmitter {
348
370
  };
349
371
  try {
350
372
  return await this.sqs.send(
351
- new ChangeMessageVisibilityBatchCommand(params)
373
+ new ChangeMessageVisibilityBatchCommand(params),
374
+ this.sqsSendOptions
352
375
  );
353
376
  } catch (err) {
354
377
  this.emit(
@@ -426,7 +449,10 @@ export class Consumer extends TypedEventEmitter {
426
449
  };
427
450
 
428
451
  try {
429
- await this.sqs.send(new DeleteMessageCommand(deleteParams));
452
+ await this.sqs.send(
453
+ new DeleteMessageCommand(deleteParams),
454
+ this.sqsSendOptions
455
+ );
430
456
  } catch (err) {
431
457
  throw toSQSError(err, `SQS delete message failed: ${err.message}`);
432
458
  }
@@ -457,7 +483,10 @@ export class Consumer extends TypedEventEmitter {
457
483
  };
458
484
 
459
485
  try {
460
- await this.sqs.send(new DeleteMessageBatchCommand(deleteParams));
486
+ await this.sqs.send(
487
+ new DeleteMessageBatchCommand(deleteParams),
488
+ this.sqsSendOptions
489
+ );
461
490
  } catch (err) {
462
491
  throw toSQSError(err, `SQS delete message failed: ${err.message}`);
463
492
  }
@@ -0,0 +1 @@
1
+ export const abortController = new AbortController();
package/src/types.ts CHANGED
@@ -106,6 +106,15 @@ export interface ConsumerOptions {
106
106
  handleMessageBatch?(messages: Message[]): Promise<Message[] | void>;
107
107
  }
108
108
 
109
+ export interface StopOptions {
110
+ /**
111
+ * Default to `false`, if you want the stop action to also abort requests to SQS
112
+ * set this to `true`.
113
+ * @defaultvalue `false`
114
+ */
115
+ abort?: boolean;
116
+ }
117
+
109
118
  export interface Events {
110
119
  /**
111
120
  * Fired after one batch of items (up to `batchSize`) has been successfully processed.
@@ -138,6 +147,10 @@ export interface Events {
138
147
  * Fired when an error occurs processing the message.
139
148
  */
140
149
  processing_error: [Error, Message];
150
+ /**
151
+ * Fired when requests to SQS were aborted.
152
+ */
153
+ aborted: [];
141
154
  /**
142
155
  * Fired when the consumer finally stops its work.
143
156
  */