sqs-consumer 6.1.0 → 6.2.0

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/src/errors.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { AWSError } from './types';
2
+
1
3
  class SQSError extends Error {
2
4
  code: string;
3
5
  statusCode: number;
@@ -20,4 +22,37 @@ class TimeoutError extends Error {
20
22
  }
21
23
  }
22
24
 
23
- export { SQSError, TimeoutError };
25
+ /**
26
+ * Checks if the error provided should be treated as a connection error.
27
+ * @param err The error that was received.
28
+ */
29
+ function isConnectionError(err: Error): boolean {
30
+ if (err instanceof SQSError) {
31
+ return (
32
+ err.statusCode === 403 ||
33
+ err.code === 'CredentialsError' ||
34
+ err.code === 'UnknownEndpoint' ||
35
+ err.code === 'AWS.SimpleQueueService.NonExistentQueue'
36
+ );
37
+ }
38
+ return false;
39
+ }
40
+
41
+ /**
42
+ * Formats an AWSError the the SQSError type.
43
+ * @param err The error object that was received.
44
+ * @param message The message that the error occurred on.
45
+ */
46
+ function toSQSError(err: AWSError, message: string): SQSError {
47
+ const sqsError = new SQSError(message);
48
+ sqsError.code = err.name;
49
+ sqsError.statusCode = err.$metadata?.httpStatusCode;
50
+ sqsError.retryable = err.$retryable?.throttling;
51
+ sqsError.service = err.$service;
52
+ sqsError.fault = err.$fault;
53
+ sqsError.time = new Date();
54
+
55
+ return sqsError;
56
+ }
57
+
58
+ export { SQSError, TimeoutError, isConnectionError, toSQSError };
package/src/types.ts CHANGED
@@ -1,36 +1,181 @@
1
1
  import { SQSClient, Message } from '@aws-sdk/client-sqs';
2
+ import { EventEmitter } from 'events';
2
3
 
3
4
  export interface ConsumerOptions {
5
+ /**
6
+ * The SQS queue URL.
7
+ */
4
8
  queueUrl: string;
9
+ /**
10
+ * List of queue attributes to retrieve (i.e.
11
+ * `['All', 'ApproximateFirstReceiveTimestamp', 'ApproximateReceiveCount']`).
12
+ * @defaultvalue `[]`
13
+ */
5
14
  attributeNames?: string[];
15
+ /**
16
+ * List of message attributes to retrieve (i.e. `['name', 'address']`).
17
+ * @defaultvalue `[]`
18
+ */
6
19
  messageAttributeNames?: string[];
20
+ /** @hidden */
7
21
  stopped?: boolean;
22
+ /**
23
+ * The number of messages to request from SQS when polling (default `1`).
24
+ *
25
+ * This cannot be higher than the
26
+ * [AWS limit of 10](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/quotas-messages.html).
27
+ * @defaultvalue `1`
28
+ */
8
29
  batchSize?: number;
30
+ /**
31
+ * The duration (in seconds) that the received messages are hidden from subsequent
32
+ * retrieve requests after being retrieved by a ReceiveMessage request.
33
+ */
9
34
  visibilityTimeout?: number;
35
+ /**
36
+ * The duration (in seconds) for which the call will wait for a message to arrive in
37
+ * the queue before returning.
38
+ * @defaultvalue `20`
39
+ */
10
40
  waitTimeSeconds?: number;
41
+ /**
42
+ * The duration (in milliseconds) to wait before retrying after an authentication error.
43
+ * @defaultvalue `10000`
44
+ */
11
45
  authenticationErrorTimeout?: number;
46
+ /**
47
+ * The duration (in milliseconds) to wait before repolling the queue.
48
+ * @defaultvalue `0`
49
+ */
12
50
  pollingWaitTimeMs?: number;
51
+ /**
52
+ * If true, sets the message visibility timeout to 0 after a `processing_error`.
53
+ * @defaultvalue `false`
54
+ */
13
55
  terminateVisibilityTimeout?: boolean;
56
+ /**
57
+ * The interval (in seconds) between requests to extend the message visibility timeout.
58
+ *
59
+ * On each heartbeat the visibility is extended by adding `visibilityTimeout` to
60
+ * the number of seconds since the start of the handler function.
61
+ *
62
+ * This value must less than `visibilityTimeout`.
63
+ */
14
64
  heartbeatInterval?: number;
65
+ /**
66
+ * An optional [SQS Client](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-sqs/classes/sqsclient.html)
67
+ * object to use if you need to configure the client manually.
68
+ */
15
69
  sqs?: SQSClient;
70
+ /**
71
+ * The AWS region.
72
+ * @defaultValue `eu-west-1`
73
+ */
16
74
  region?: string;
75
+ /**
76
+ * Time in ms to wait for `handleMessage` to process a message before timing out.
77
+ *
78
+ * Emits `timeout_error` on timeout. By default, if `handleMessage` times out,
79
+ * the unprocessed message returns to the end of the queue.
80
+ */
17
81
  handleMessageTimeout?: number;
82
+ /**
83
+ * Default to `true`, if you don't want the package to delete messages from sqs
84
+ * set this to `false`.
85
+ * @defaultvalue `true`
86
+ */
18
87
  shouldDeleteMessages?: boolean;
19
- handleMessage?(message: Message): Promise<void>;
88
+ /**
89
+ * An `async` function (or function that returns a `Promise`) to be called whenever
90
+ * a message is received.
91
+ *
92
+ * In the case that you need to acknowledge the message, return an object containing
93
+ * the MessageId that you'd like to acknowledge.
94
+ */
95
+ handleMessage?(message: Message): Promise<Message | void>;
96
+ /**
97
+ * An `async` function (or function that returns a `Promise`) to be called whenever
98
+ * a batch of messages is received. Similar to `handleMessage` but will receive the
99
+ * list of messages, not each message individually.
100
+ *
101
+ * **If both are set, `handleMessageBatch` overrides `handleMessage`**.
102
+ *
103
+ * In the case that you need to ack only some of the messages, return an array with
104
+ * the successful messages only.
105
+ */
20
106
  handleMessageBatch?(messages: Message[]): Promise<Message[] | void>;
21
107
  }
22
108
 
23
109
  export interface Events {
110
+ /**
111
+ * Fired after one batch of items (up to `batchSize`) has been successfully processed.
112
+ */
24
113
  response_processed: [];
114
+ /**
115
+ * Fired when the queue is empty (All messages have been consumed).
116
+ */
25
117
  empty: [];
118
+ /**
119
+ * Fired when a message is received.
120
+ */
26
121
  message_received: [Message];
122
+ /**
123
+ * Fired when a message is successfully processed and removed from the queue.
124
+ */
27
125
  message_processed: [Message];
126
+ /**
127
+ * Fired when an error occurs interacting with the queue.
128
+ *
129
+ * If the error correlates to a message, that message is included in Params
130
+ */
28
131
  error: [Error, void | Message | Message[]];
132
+ /**
133
+ * Fired when `handleMessageTimeout` is supplied as an option and if
134
+ * `handleMessage` times out.
135
+ */
29
136
  timeout_error: [Error, Message];
137
+ /**
138
+ * Fired when an error occurs processing the message.
139
+ */
30
140
  processing_error: [Error, Message];
141
+ /**
142
+ * Fired when the consumer finally stops its work.
143
+ */
31
144
  stopped: [];
32
145
  }
33
146
 
147
+ export class TypedEventEmitter extends EventEmitter {
148
+ /**
149
+ * Trigger a listener on all emitted events
150
+ * @param event The name of the event to listen to
151
+ * @param listener A function to trigger when the event is emitted
152
+ */
153
+ on<E extends keyof Events>(
154
+ event: E,
155
+ listener: (...args: Events[E]) => void
156
+ ): this {
157
+ return super.on(event, listener);
158
+ }
159
+ /**
160
+ * Trigger a listener only once for an emitted event
161
+ * @param event The name of the event to listen to
162
+ * @param listener A function to trigger when the event is emitted
163
+ */
164
+ once<E extends keyof Events>(
165
+ event: E,
166
+ listener: (...args: Events[E]) => void
167
+ ): this {
168
+ return super.on(event, listener);
169
+ }
170
+ /**
171
+ * Emits an event with the provided arguments
172
+ * @param event The name of the event to emit
173
+ */
174
+ emit<E extends keyof Events>(event: E, ...args: Events[E]): boolean {
175
+ return super.emit(event, ...args);
176
+ }
177
+ }
178
+
34
179
  export type AWSError = {
35
180
  /**
36
181
  * Name, eg. ConditionalCheckFailedException
@@ -0,0 +1,45 @@
1
+ import { ReceiveMessageCommandOutput } from '@aws-sdk/client-sqs';
2
+
3
+ import { ConsumerOptions } from './types';
4
+
5
+ const requiredOptions = [
6
+ 'queueUrl',
7
+ // only one of handleMessage / handleMessagesBatch is required
8
+ 'handleMessage|handleMessageBatch'
9
+ ];
10
+
11
+ /**
12
+ * Ensure that the required options have been set.
13
+ * @param options The options that have been set by the application.
14
+ */
15
+ function assertOptions(options: ConsumerOptions): void {
16
+ requiredOptions.forEach((option) => {
17
+ const possibilities = option.split('|');
18
+ if (!possibilities.find((p) => options[p])) {
19
+ throw new Error(
20
+ `Missing SQS consumer option [ ${possibilities.join(' or ')} ].`
21
+ );
22
+ }
23
+ });
24
+
25
+ if (options.batchSize > 10 || options.batchSize < 1) {
26
+ throw new Error('SQS batchSize option must be between 1 and 10.');
27
+ }
28
+
29
+ if (
30
+ options.heartbeatInterval &&
31
+ !(options.heartbeatInterval < options.visibilityTimeout)
32
+ ) {
33
+ throw new Error('heartbeatInterval must be less than visibilityTimeout.');
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Determine if the response from SQS has messages in it.
39
+ * @param response The response from SQS.
40
+ */
41
+ function hasMessages(response: ReceiveMessageCommandOutput): boolean {
42
+ return response.Messages && response.Messages.length > 0;
43
+ }
44
+
45
+ export { hasMessages, assertOptions };
package/typedoc.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "https://typedoc.org/schema.json",
3
+ "sort": ["kind", "instance-first", "required-first", "alphabetical"],
4
+ "treatWarningsAsErrors": false,
5
+ "searchInComments": true,
6
+ "entryPoints": ["./src/index.ts"],
7
+ "out": "public",
8
+ "name": "SQS Consumer",
9
+ "hideGenerator": true,
10
+ "navigationLinks": {
11
+ "GitHub": "https://github.com/bbc/sqs-consumer"
12
+ }
13
+ }