sqs-consumer 14.2.4-canary.2 → 14.2.4
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/CHANGELOG.md +5 -2
- package/dist/cjs/consumer.js +14 -6
- package/dist/cjs/errors.d.ts +2 -2
- package/dist/cjs/types.d.ts +1 -1
- package/dist/cjs/validation.d.ts +2 -2
- package/dist/cjs/validation.js +4 -2
- package/dist/esm/consumer.js +14 -6
- package/dist/esm/errors.d.ts +2 -2
- package/dist/esm/types.d.ts +1 -1
- package/dist/esm/validation.d.ts +2 -2
- package/dist/esm/validation.js +4 -2
- package/package.json +148 -40
- package/src/consumer.ts +83 -32
- package/src/errors.ts +2 -2
- package/src/types.ts +5 -2
- package/src/validation.ts +19 -7
- package/.releaserc.json +0 -86
- package/vitest.config.ts +0 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
## [14.2.4
|
|
1
|
+
## [14.2.4](https://github.com/bbc/sqs-consumer/compare/v14.2.3...v14.2.4) (2026-03-20)
|
|
2
2
|
|
|
3
3
|
### Chores
|
|
4
4
|
|
|
5
|
-
*
|
|
5
|
+
* **deps:** bump actions/setup-node from 6.2.0 to 6.3.0 ([#738](https://github.com/bbc/sqs-consumer/issues/738)) ([75a85cc](https://github.com/bbc/sqs-consumer/commit/75a85cc4c9adf44144b756dea0de1fc01b842f56))
|
|
6
|
+
* **deps:** bump github/codeql-action from 4.32.5 to 4.33.0 ([#741](https://github.com/bbc/sqs-consumer/issues/741)) ([aa5165f](https://github.com/bbc/sqs-consumer/commit/aa5165fd5d7eb7fabf5b7bef228f945ffc3a2a79))
|
|
7
|
+
* **deps:** bump oven-sh/setup-bun from 2.1.2 to 2.2.0 ([#740](https://github.com/bbc/sqs-consumer/issues/740)) ([86abfc2](https://github.com/bbc/sqs-consumer/commit/86abfc29ed3a49d1bee6333b5efe5e08d8afb5a9))
|
|
8
|
+
* **deps:** bump zgosalvez/github-actions-report-lcov ([#742](https://github.com/bbc/sqs-consumer/issues/742)) ([57fad30](https://github.com/bbc/sqs-consumer/commit/57fad30af39ec387797be8fef5be9afe52a9473b))
|
package/dist/cjs/consumer.js
CHANGED
|
@@ -26,13 +26,16 @@ class Consumer extends emitter_js_1.TypedEventEmitter {
|
|
|
26
26
|
this.handleMessageTimeout = options.handleMessageTimeout;
|
|
27
27
|
this.attributeNames = options.attributeNames || [];
|
|
28
28
|
this.messageAttributeNames = options.messageAttributeNames || [];
|
|
29
|
-
this.messageSystemAttributeNames =
|
|
29
|
+
this.messageSystemAttributeNames =
|
|
30
|
+
options.messageSystemAttributeNames || [];
|
|
30
31
|
this.batchSize = options.batchSize || 1;
|
|
31
32
|
this.visibilityTimeout = options.visibilityTimeout;
|
|
32
|
-
this.terminateVisibilityTimeout =
|
|
33
|
+
this.terminateVisibilityTimeout =
|
|
34
|
+
options.terminateVisibilityTimeout || false;
|
|
33
35
|
this.heartbeatInterval = options.heartbeatInterval;
|
|
34
36
|
this.waitTimeSeconds = options.waitTimeSeconds ?? 20;
|
|
35
|
-
this.authenticationErrorTimeout =
|
|
37
|
+
this.authenticationErrorTimeout =
|
|
38
|
+
options.authenticationErrorTimeout ?? 10000;
|
|
36
39
|
this.pollingWaitTimeMs = options.pollingWaitTimeMs ?? 0;
|
|
37
40
|
this.pollingCompleteWaitTimeMs = options.pollingCompleteWaitTimeMs ?? 0;
|
|
38
41
|
this.shouldDeleteMessages = options.shouldDeleteMessages ?? true;
|
|
@@ -109,7 +112,8 @@ class Consumer extends emitter_js_1.TypedEventEmitter {
|
|
|
109
112
|
this.emit("stopped");
|
|
110
113
|
return;
|
|
111
114
|
}
|
|
112
|
-
const exceededTimeout = Date.now() - this.stopRequestedAtTimestamp >
|
|
115
|
+
const exceededTimeout = Date.now() - this.stopRequestedAtTimestamp >
|
|
116
|
+
this.pollingCompleteWaitTimeMs;
|
|
113
117
|
if (exceededTimeout) {
|
|
114
118
|
this.emit("waiting_for_polling_to_complete_timeout_exceeded");
|
|
115
119
|
this.emit("stopped");
|
|
@@ -268,7 +272,9 @@ class Consumer extends emitter_js_1.TypedEventEmitter {
|
|
|
268
272
|
await this.changeVisibilityTimeout(message, timeout);
|
|
269
273
|
}
|
|
270
274
|
else {
|
|
271
|
-
const timeout = this.terminateVisibilityTimeout === true
|
|
275
|
+
const timeout = this.terminateVisibilityTimeout === true
|
|
276
|
+
? 0
|
|
277
|
+
: this.terminateVisibilityTimeout;
|
|
272
278
|
await this.changeVisibilityTimeout(message, timeout);
|
|
273
279
|
}
|
|
274
280
|
}
|
|
@@ -308,7 +314,9 @@ class Consumer extends emitter_js_1.TypedEventEmitter {
|
|
|
308
314
|
await this.changeVisibilityTimeoutBatch(messages, timeout);
|
|
309
315
|
}
|
|
310
316
|
else {
|
|
311
|
-
const timeout = this.terminateVisibilityTimeout === true
|
|
317
|
+
const timeout = this.terminateVisibilityTimeout === true
|
|
318
|
+
? 0
|
|
319
|
+
: this.terminateVisibilityTimeout;
|
|
312
320
|
await this.changeVisibilityTimeoutBatch(messages, timeout);
|
|
313
321
|
}
|
|
314
322
|
}
|
package/dist/cjs/errors.d.ts
CHANGED
package/dist/cjs/types.d.ts
CHANGED
package/dist/cjs/validation.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { ReceiveMessageCommandOutput } from "@aws-sdk/client-sqs";
|
|
2
|
+
import { ConsumerOptions } from "./types.js";
|
|
3
3
|
declare function validateOption(option: string, value: any, allOptions: {
|
|
4
4
|
[key: string]: any;
|
|
5
5
|
}, strict?: boolean): void;
|
package/dist/cjs/validation.js
CHANGED
|
@@ -16,12 +16,14 @@ function validateOption(option, value, allOptions, strict) {
|
|
|
16
16
|
}
|
|
17
17
|
break;
|
|
18
18
|
case "heartbeatInterval":
|
|
19
|
-
if (!allOptions.visibilityTimeout ||
|
|
19
|
+
if (!allOptions.visibilityTimeout ||
|
|
20
|
+
value >= allOptions.visibilityTimeout) {
|
|
20
21
|
throw new Error("heartbeatInterval must be less than visibilityTimeout.");
|
|
21
22
|
}
|
|
22
23
|
break;
|
|
23
24
|
case "visibilityTimeout":
|
|
24
|
-
if (allOptions.heartbeatInterval &&
|
|
25
|
+
if (allOptions.heartbeatInterval &&
|
|
26
|
+
value <= allOptions.heartbeatInterval) {
|
|
25
27
|
throw new Error("heartbeatInterval must be less than visibilityTimeout.");
|
|
26
28
|
}
|
|
27
29
|
break;
|
package/dist/esm/consumer.js
CHANGED
|
@@ -23,13 +23,16 @@ export class Consumer extends TypedEventEmitter {
|
|
|
23
23
|
this.handleMessageTimeout = options.handleMessageTimeout;
|
|
24
24
|
this.attributeNames = options.attributeNames || [];
|
|
25
25
|
this.messageAttributeNames = options.messageAttributeNames || [];
|
|
26
|
-
this.messageSystemAttributeNames =
|
|
26
|
+
this.messageSystemAttributeNames =
|
|
27
|
+
options.messageSystemAttributeNames || [];
|
|
27
28
|
this.batchSize = options.batchSize || 1;
|
|
28
29
|
this.visibilityTimeout = options.visibilityTimeout;
|
|
29
|
-
this.terminateVisibilityTimeout =
|
|
30
|
+
this.terminateVisibilityTimeout =
|
|
31
|
+
options.terminateVisibilityTimeout || false;
|
|
30
32
|
this.heartbeatInterval = options.heartbeatInterval;
|
|
31
33
|
this.waitTimeSeconds = options.waitTimeSeconds ?? 20;
|
|
32
|
-
this.authenticationErrorTimeout =
|
|
34
|
+
this.authenticationErrorTimeout =
|
|
35
|
+
options.authenticationErrorTimeout ?? 10000;
|
|
33
36
|
this.pollingWaitTimeMs = options.pollingWaitTimeMs ?? 0;
|
|
34
37
|
this.pollingCompleteWaitTimeMs = options.pollingCompleteWaitTimeMs ?? 0;
|
|
35
38
|
this.shouldDeleteMessages = options.shouldDeleteMessages ?? true;
|
|
@@ -106,7 +109,8 @@ export class Consumer extends TypedEventEmitter {
|
|
|
106
109
|
this.emit("stopped");
|
|
107
110
|
return;
|
|
108
111
|
}
|
|
109
|
-
const exceededTimeout = Date.now() - this.stopRequestedAtTimestamp >
|
|
112
|
+
const exceededTimeout = Date.now() - this.stopRequestedAtTimestamp >
|
|
113
|
+
this.pollingCompleteWaitTimeMs;
|
|
110
114
|
if (exceededTimeout) {
|
|
111
115
|
this.emit("waiting_for_polling_to_complete_timeout_exceeded");
|
|
112
116
|
this.emit("stopped");
|
|
@@ -265,7 +269,9 @@ export class Consumer extends TypedEventEmitter {
|
|
|
265
269
|
await this.changeVisibilityTimeout(message, timeout);
|
|
266
270
|
}
|
|
267
271
|
else {
|
|
268
|
-
const timeout = this.terminateVisibilityTimeout === true
|
|
272
|
+
const timeout = this.terminateVisibilityTimeout === true
|
|
273
|
+
? 0
|
|
274
|
+
: this.terminateVisibilityTimeout;
|
|
269
275
|
await this.changeVisibilityTimeout(message, timeout);
|
|
270
276
|
}
|
|
271
277
|
}
|
|
@@ -305,7 +311,9 @@ export class Consumer extends TypedEventEmitter {
|
|
|
305
311
|
await this.changeVisibilityTimeoutBatch(messages, timeout);
|
|
306
312
|
}
|
|
307
313
|
else {
|
|
308
|
-
const timeout = this.terminateVisibilityTimeout === true
|
|
314
|
+
const timeout = this.terminateVisibilityTimeout === true
|
|
315
|
+
? 0
|
|
316
|
+
: this.terminateVisibilityTimeout;
|
|
309
317
|
await this.changeVisibilityTimeoutBatch(messages, timeout);
|
|
310
318
|
}
|
|
311
319
|
}
|
package/dist/esm/errors.d.ts
CHANGED
package/dist/esm/types.d.ts
CHANGED
package/dist/esm/validation.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { ReceiveMessageCommandOutput } from "@aws-sdk/client-sqs";
|
|
2
|
+
import { ConsumerOptions } from "./types.js";
|
|
3
3
|
declare function validateOption(option: string, value: any, allOptions: {
|
|
4
4
|
[key: string]: any;
|
|
5
5
|
}, strict?: boolean): void;
|
package/dist/esm/validation.js
CHANGED
|
@@ -11,12 +11,14 @@ function validateOption(option, value, allOptions, strict) {
|
|
|
11
11
|
}
|
|
12
12
|
break;
|
|
13
13
|
case "heartbeatInterval":
|
|
14
|
-
if (!allOptions.visibilityTimeout ||
|
|
14
|
+
if (!allOptions.visibilityTimeout ||
|
|
15
|
+
value >= allOptions.visibilityTimeout) {
|
|
15
16
|
throw new Error("heartbeatInterval must be less than visibilityTimeout.");
|
|
16
17
|
}
|
|
17
18
|
break;
|
|
18
19
|
case "visibilityTimeout":
|
|
19
|
-
if (allOptions.heartbeatInterval &&
|
|
20
|
+
if (allOptions.heartbeatInterval &&
|
|
21
|
+
value <= allOptions.heartbeatInterval) {
|
|
20
22
|
throw new Error("heartbeatInterval must be less than visibilityTimeout.");
|
|
21
23
|
}
|
|
22
24
|
break;
|
package/package.json
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sqs-consumer",
|
|
3
|
-
"version": "14.2.4
|
|
3
|
+
"version": "14.2.4",
|
|
4
4
|
"description": "Build SQS-based Node applications without the boilerplate",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"consumer",
|
|
7
|
-
"queue",
|
|
8
|
-
"sqs"
|
|
9
|
-
],
|
|
10
|
-
"homepage": "https://bbc.github.io/sqs-consumer/",
|
|
11
|
-
"bugs": {
|
|
12
|
-
"url": "https://github.com/bbc/sqs-consumer/issues"
|
|
13
|
-
},
|
|
14
|
-
"license": "Apache-2.0",
|
|
15
|
-
"repository": {
|
|
16
|
-
"type": "git",
|
|
17
|
-
"url": "git+https://github.com/bbc/sqs-consumer.git"
|
|
18
|
-
},
|
|
19
5
|
"type": "module",
|
|
20
6
|
"main": "dist/cjs/index.js",
|
|
21
7
|
"types": "dist/cjs/index.d.ts",
|
|
@@ -31,8 +17,8 @@
|
|
|
31
17
|
}
|
|
32
18
|
}
|
|
33
19
|
},
|
|
34
|
-
"
|
|
35
|
-
"
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=20.0.0"
|
|
36
22
|
},
|
|
37
23
|
"scripts": {
|
|
38
24
|
"clean": "rm -fr dist/*",
|
|
@@ -42,25 +28,126 @@
|
|
|
42
28
|
"watch": "tsc --watch",
|
|
43
29
|
"prepublishOnly": "npm run build",
|
|
44
30
|
"release": "semantic-release",
|
|
45
|
-
"test:unit": "
|
|
46
|
-
"test:unit:report": "
|
|
31
|
+
"test:unit": "mocha --recursive --full-trace --exit",
|
|
32
|
+
"test:unit:report": "mocha --recursive --full-trace --exit --reporter json > test/reports/test-results.json",
|
|
47
33
|
"pretest:integration:init": "npm run build",
|
|
48
|
-
"test:integration:init": "
|
|
34
|
+
"test:integration:init": "sh ./test/scripts/initIntTests.sh",
|
|
49
35
|
"test:integration": "npm run test:integration:init && cucumber-js --config ./test/config/cucumber.mjs",
|
|
50
36
|
"test": "npm run test:unit:report && npm run test:integration",
|
|
51
|
-
"coverage": "
|
|
52
|
-
"lcov": "
|
|
53
|
-
"
|
|
54
|
-
"lint": "
|
|
55
|
-
"
|
|
56
|
-
"format": "
|
|
57
|
-
"
|
|
58
|
-
"check": "npm run lint && npm run format:check && npm run typecheck && npm run test",
|
|
37
|
+
"coverage": "c8 mocha && c8 report --reporter=html && c8 report --reporter=json-summary",
|
|
38
|
+
"lcov": "c8 mocha && c8 report --reporter=lcov",
|
|
39
|
+
"lint": "eslint .",
|
|
40
|
+
"lint:fix": "eslint . --fix",
|
|
41
|
+
"format": "prettier --log-level warn --write \"**/*.{js,json,jsx,md,ts,tsx,html}\"",
|
|
42
|
+
"format:check": "prettier --check \"**/*.{js,json,jsx,md,ts,tsx,html}\"",
|
|
43
|
+
"posttest": "npm run lint && npm run format:check",
|
|
59
44
|
"generate-docs": "typedoc"
|
|
60
45
|
},
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+https://github.com/bbc/sqs-consumer.git"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/bbc/sqs-consumer/issues"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://bbc.github.io/sqs-consumer/",
|
|
54
|
+
"keywords": [
|
|
55
|
+
"sqs",
|
|
56
|
+
"queue",
|
|
57
|
+
"consumer"
|
|
58
|
+
],
|
|
59
|
+
"license": "Apache-2.0",
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"provenance": true
|
|
62
|
+
},
|
|
63
|
+
"release": {
|
|
64
|
+
"branches": [
|
|
65
|
+
"main",
|
|
66
|
+
"*.x",
|
|
67
|
+
{
|
|
68
|
+
"name": "canary",
|
|
69
|
+
"prerelease": true
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
"plugins": [
|
|
73
|
+
[
|
|
74
|
+
"@semantic-release/commit-analyzer",
|
|
75
|
+
{
|
|
76
|
+
"preset": "conventionalcommits",
|
|
77
|
+
"releaseRules": [
|
|
78
|
+
{
|
|
79
|
+
"type": "breaking",
|
|
80
|
+
"release": "major"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"type": "feat",
|
|
84
|
+
"release": "minor"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"type": "chore",
|
|
88
|
+
"release": "patch"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"type": "fix",
|
|
92
|
+
"release": "patch"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"type": "docs",
|
|
96
|
+
"release": "patch"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"type": "refactor",
|
|
100
|
+
"release": "patch"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"type": "test",
|
|
104
|
+
"release": "patch"
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
[
|
|
110
|
+
"@semantic-release/release-notes-generator",
|
|
111
|
+
{
|
|
112
|
+
"preset": "conventionalcommits",
|
|
113
|
+
"presetConfig": {
|
|
114
|
+
"types": [
|
|
115
|
+
{
|
|
116
|
+
"type": "feat",
|
|
117
|
+
"section": "Features"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"type": "fix",
|
|
121
|
+
"section": "Bug Fixes"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"type": "chore",
|
|
125
|
+
"section": "Chores"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"type": "docs",
|
|
129
|
+
"section": "Documentation"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"type": "refactor",
|
|
133
|
+
"section": "Refactors"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"type": "test",
|
|
137
|
+
"section": "Tests"
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
],
|
|
143
|
+
"@semantic-release/changelog",
|
|
144
|
+
"@semantic-release/github",
|
|
145
|
+
"@semantic-release/npm",
|
|
146
|
+
"@sebbo2002/semantic-release-jsr"
|
|
147
|
+
]
|
|
148
|
+
},
|
|
149
|
+
"overrides": {
|
|
150
|
+
"cross-spawn": "^7.0.3"
|
|
64
151
|
},
|
|
65
152
|
"devDependencies": {
|
|
66
153
|
"@cucumber/cucumber": "^12.6.0",
|
|
@@ -72,30 +159,51 @@
|
|
|
72
159
|
"@semantic-release/npm": "^13.1.4",
|
|
73
160
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
74
161
|
"@types/chai": "^5.2.2",
|
|
162
|
+
"@types/mocha": "^10.0.10",
|
|
75
163
|
"@types/node": "^25.2.3",
|
|
76
164
|
"@types/sinon": "^17.0.4",
|
|
77
|
-
"@
|
|
165
|
+
"@typescript-eslint/eslint-plugin": "^8.55.0",
|
|
166
|
+
"@typescript-eslint/parser": "^8.50.1",
|
|
167
|
+
"c8": "^10.1.3",
|
|
78
168
|
"chai": "^6.2.2",
|
|
79
169
|
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
170
|
+
"eslint": "^9.39.3",
|
|
171
|
+
"eslint-config-eslint": "^13.0.0",
|
|
80
172
|
"jsr": "^0.14.3",
|
|
81
|
-
"
|
|
82
|
-
"oxlint": "^1.56.0",
|
|
173
|
+
"mocha": "^11.7.5",
|
|
83
174
|
"p-event": "^7.0.2",
|
|
175
|
+
"prettier": "^3.8.1",
|
|
84
176
|
"semantic-release": "^25.0.3",
|
|
85
177
|
"sinon": "^21.0.0",
|
|
86
178
|
"sqs-producer": "^8.0.2",
|
|
87
179
|
"ts-node": "^10.9.2",
|
|
88
180
|
"typedoc": "^0.28.16",
|
|
89
|
-
"typescript": "^5.9.3"
|
|
90
|
-
|
|
181
|
+
"typescript": "^5.9.3"
|
|
182
|
+
},
|
|
183
|
+
"dependencies": {
|
|
184
|
+
"@aws-sdk/client-sqs": "^3.989.0",
|
|
185
|
+
"debug": "^4.4.3"
|
|
91
186
|
},
|
|
92
187
|
"peerDependencies": {
|
|
93
188
|
"@aws-sdk/client-sqs": "^3.989.0"
|
|
94
189
|
},
|
|
95
|
-
"
|
|
96
|
-
"
|
|
190
|
+
"mocha": {
|
|
191
|
+
"extensions": [
|
|
192
|
+
"ts"
|
|
193
|
+
],
|
|
194
|
+
"spec": "test/tests/**/**/*.test.ts",
|
|
195
|
+
"node-option": [
|
|
196
|
+
"loader=ts-node/esm"
|
|
197
|
+
]
|
|
97
198
|
},
|
|
98
|
-
"
|
|
99
|
-
"
|
|
199
|
+
"c8": {
|
|
200
|
+
"include": [
|
|
201
|
+
"src/**/*.ts"
|
|
202
|
+
],
|
|
203
|
+
"extension": [
|
|
204
|
+
".ts"
|
|
205
|
+
],
|
|
206
|
+
"sourceMap": true,
|
|
207
|
+
"instrument": true
|
|
100
208
|
}
|
|
101
209
|
}
|
package/src/consumer.ts
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SQSClient,
|
|
3
|
-
ChangeMessageVisibilityCommand,
|
|
4
|
-
ChangeMessageVisibilityBatchCommand,
|
|
5
|
-
DeleteMessageCommand,
|
|
6
|
-
DeleteMessageBatchCommand,
|
|
7
|
-
ReceiveMessageCommand,
|
|
8
|
-
} from "@aws-sdk/client-sqs";
|
|
9
|
-
import type {
|
|
10
3
|
Message,
|
|
4
|
+
ChangeMessageVisibilityCommand,
|
|
11
5
|
ChangeMessageVisibilityCommandInput,
|
|
12
6
|
ChangeMessageVisibilityCommandOutput,
|
|
7
|
+
ChangeMessageVisibilityBatchCommand,
|
|
13
8
|
ChangeMessageVisibilityBatchCommandInput,
|
|
14
9
|
ChangeMessageVisibilityBatchCommandOutput,
|
|
10
|
+
DeleteMessageCommand,
|
|
15
11
|
DeleteMessageCommandInput,
|
|
12
|
+
DeleteMessageBatchCommand,
|
|
16
13
|
DeleteMessageBatchCommandInput,
|
|
14
|
+
ReceiveMessageCommand,
|
|
17
15
|
ReceiveMessageCommandInput,
|
|
18
16
|
ReceiveMessageCommandOutput,
|
|
19
17
|
QueueAttributeName,
|
|
20
18
|
MessageSystemAttributeName,
|
|
21
19
|
} from "@aws-sdk/client-sqs";
|
|
22
20
|
|
|
23
|
-
import type {
|
|
21
|
+
import type {
|
|
22
|
+
ConsumerOptions,
|
|
23
|
+
StopOptions,
|
|
24
|
+
UpdatableOptions,
|
|
25
|
+
} from "./types.js";
|
|
24
26
|
import { TypedEventEmitter } from "./emitter.js";
|
|
25
27
|
import {
|
|
26
28
|
SQSError,
|
|
@@ -43,7 +45,9 @@ export class Consumer extends TypedEventEmitter {
|
|
|
43
45
|
private isFifoQueue: boolean;
|
|
44
46
|
private suppressFifoWarning: boolean;
|
|
45
47
|
private handleMessage: (message: Message) => Promise<Message | undefined>;
|
|
46
|
-
private handleMessageBatch: (
|
|
48
|
+
private handleMessageBatch: (
|
|
49
|
+
messages: Message[],
|
|
50
|
+
) => Promise<Message[] | undefined>;
|
|
47
51
|
private preReceiveMessageCallback?: () => Promise<void>;
|
|
48
52
|
private postReceiveMessageCallback?: () => Promise<void>;
|
|
49
53
|
private sqs: SQSClient;
|
|
@@ -55,7 +59,10 @@ export class Consumer extends TypedEventEmitter {
|
|
|
55
59
|
private alwaysAcknowledge: boolean;
|
|
56
60
|
private batchSize: number;
|
|
57
61
|
private visibilityTimeout: number;
|
|
58
|
-
private terminateVisibilityTimeout:
|
|
62
|
+
private terminateVisibilityTimeout:
|
|
63
|
+
| boolean
|
|
64
|
+
| number
|
|
65
|
+
| ((message: Message[]) => number);
|
|
59
66
|
private waitTimeSeconds: number;
|
|
60
67
|
private authenticationErrorTimeout: number;
|
|
61
68
|
private pollingWaitTimeMs: number;
|
|
@@ -80,13 +87,16 @@ export class Consumer extends TypedEventEmitter {
|
|
|
80
87
|
this.handleMessageTimeout = options.handleMessageTimeout;
|
|
81
88
|
this.attributeNames = options.attributeNames || [];
|
|
82
89
|
this.messageAttributeNames = options.messageAttributeNames || [];
|
|
83
|
-
this.messageSystemAttributeNames =
|
|
90
|
+
this.messageSystemAttributeNames =
|
|
91
|
+
options.messageSystemAttributeNames || [];
|
|
84
92
|
this.batchSize = options.batchSize || 1;
|
|
85
93
|
this.visibilityTimeout = options.visibilityTimeout;
|
|
86
|
-
this.terminateVisibilityTimeout =
|
|
94
|
+
this.terminateVisibilityTimeout =
|
|
95
|
+
options.terminateVisibilityTimeout || false;
|
|
87
96
|
this.heartbeatInterval = options.heartbeatInterval;
|
|
88
97
|
this.waitTimeSeconds = options.waitTimeSeconds ?? 20;
|
|
89
|
-
this.authenticationErrorTimeout =
|
|
98
|
+
this.authenticationErrorTimeout =
|
|
99
|
+
options.authenticationErrorTimeout ?? 10000;
|
|
90
100
|
this.pollingWaitTimeMs = options.pollingWaitTimeMs ?? 0;
|
|
91
101
|
this.pollingCompleteWaitTimeMs = options.pollingCompleteWaitTimeMs ?? 0;
|
|
92
102
|
this.shouldDeleteMessages = options.shouldDeleteMessages ?? true;
|
|
@@ -176,7 +186,8 @@ export class Consumer extends TypedEventEmitter {
|
|
|
176
186
|
}
|
|
177
187
|
|
|
178
188
|
const exceededTimeout: boolean =
|
|
179
|
-
Date.now() - this.stopRequestedAtTimestamp >
|
|
189
|
+
Date.now() - this.stopRequestedAtTimestamp >
|
|
190
|
+
this.pollingCompleteWaitTimeMs;
|
|
180
191
|
if (exceededTimeout) {
|
|
181
192
|
this.emit("waiting_for_polling_to_complete_timeout_exceeded");
|
|
182
193
|
this.emit("stopped");
|
|
@@ -206,7 +217,10 @@ export class Consumer extends TypedEventEmitter {
|
|
|
206
217
|
* @param option The option to validate and then update
|
|
207
218
|
* @param value The value to set the provided option to
|
|
208
219
|
*/
|
|
209
|
-
public updateOption(
|
|
220
|
+
public updateOption(
|
|
221
|
+
option: UpdatableOptions,
|
|
222
|
+
value: ConsumerOptions[UpdatableOptions],
|
|
223
|
+
): void {
|
|
210
224
|
validateOption(option, value, this, true);
|
|
211
225
|
|
|
212
226
|
this[option] = value;
|
|
@@ -237,7 +251,8 @@ export class Consumer extends TypedEventEmitter {
|
|
|
237
251
|
private poll(): void {
|
|
238
252
|
if (this.stopped) {
|
|
239
253
|
logger.debug("cancelling_poll", {
|
|
240
|
-
detail:
|
|
254
|
+
detail:
|
|
255
|
+
"Poll was called while consumer was stopped, cancelling poll...",
|
|
241
256
|
});
|
|
242
257
|
return;
|
|
243
258
|
}
|
|
@@ -256,13 +271,16 @@ export class Consumer extends TypedEventEmitter {
|
|
|
256
271
|
WaitTimeSeconds: this.waitTimeSeconds,
|
|
257
272
|
VisibilityTimeout: this.visibilityTimeout,
|
|
258
273
|
})
|
|
259
|
-
.then((output: ReceiveMessageCommandOutput) =>
|
|
274
|
+
.then((output: ReceiveMessageCommandOutput) =>
|
|
275
|
+
this.handleSqsResponse(output),
|
|
276
|
+
)
|
|
260
277
|
.catch((err): void => {
|
|
261
278
|
this.emitError(err);
|
|
262
279
|
if (isConnectionError(err)) {
|
|
263
280
|
logger.debug("authentication_error", {
|
|
264
281
|
code: err.code || "Unknown",
|
|
265
|
-
detail:
|
|
282
|
+
detail:
|
|
283
|
+
"There was an authentication error. Pausing before retrying.",
|
|
266
284
|
});
|
|
267
285
|
currentPollingTimeout = this.authenticationErrorTimeout;
|
|
268
286
|
}
|
|
@@ -272,7 +290,10 @@ export class Consumer extends TypedEventEmitter {
|
|
|
272
290
|
if (this.pollingTimeoutId) {
|
|
273
291
|
clearTimeout(this.pollingTimeoutId);
|
|
274
292
|
}
|
|
275
|
-
this.pollingTimeoutId = setTimeout(
|
|
293
|
+
this.pollingTimeoutId = setTimeout(
|
|
294
|
+
() => this.poll(),
|
|
295
|
+
currentPollingTimeout,
|
|
296
|
+
);
|
|
276
297
|
})
|
|
277
298
|
.catch((err): void => {
|
|
278
299
|
this.emitError(err);
|
|
@@ -317,13 +338,17 @@ export class Consumer extends TypedEventEmitter {
|
|
|
317
338
|
* the message handler.
|
|
318
339
|
* @param response The output from AWS SQS
|
|
319
340
|
*/
|
|
320
|
-
private async handleSqsResponse(
|
|
341
|
+
private async handleSqsResponse(
|
|
342
|
+
response: ReceiveMessageCommandOutput,
|
|
343
|
+
): Promise<void> {
|
|
321
344
|
if (hasMessages(response)) {
|
|
322
345
|
if (this.handleMessageBatch) {
|
|
323
346
|
await this.processMessageBatch(response.Messages);
|
|
324
347
|
} else {
|
|
325
348
|
await Promise.all(
|
|
326
|
-
response.Messages.map((message: Message) =>
|
|
349
|
+
response.Messages.map((message: Message) =>
|
|
350
|
+
this.processMessage(message),
|
|
351
|
+
),
|
|
327
352
|
);
|
|
328
353
|
}
|
|
329
354
|
|
|
@@ -364,7 +389,9 @@ export class Consumer extends TypedEventEmitter {
|
|
|
364
389
|
await this.changeVisibilityTimeout(message, timeout);
|
|
365
390
|
} else {
|
|
366
391
|
const timeout =
|
|
367
|
-
this.terminateVisibilityTimeout === true
|
|
392
|
+
this.terminateVisibilityTimeout === true
|
|
393
|
+
? 0
|
|
394
|
+
: this.terminateVisibilityTimeout;
|
|
368
395
|
await this.changeVisibilityTimeout(message, timeout);
|
|
369
396
|
}
|
|
370
397
|
}
|
|
@@ -409,7 +436,9 @@ export class Consumer extends TypedEventEmitter {
|
|
|
409
436
|
await this.changeVisibilityTimeoutBatch(messages, timeout);
|
|
410
437
|
} else {
|
|
411
438
|
const timeout =
|
|
412
|
-
this.terminateVisibilityTimeout === true
|
|
439
|
+
this.terminateVisibilityTimeout === true
|
|
440
|
+
? 0
|
|
441
|
+
: this.terminateVisibilityTimeout;
|
|
413
442
|
await this.changeVisibilityTimeoutBatch(messages, timeout);
|
|
414
443
|
}
|
|
415
444
|
}
|
|
@@ -422,10 +451,16 @@ export class Consumer extends TypedEventEmitter {
|
|
|
422
451
|
* Trigger a function on a set interval
|
|
423
452
|
* @param heartbeatFn The function that should be triggered
|
|
424
453
|
*/
|
|
425
|
-
private startHeartbeat(
|
|
454
|
+
private startHeartbeat(
|
|
455
|
+
message?: Message,
|
|
456
|
+
messages?: Message[],
|
|
457
|
+
): NodeJS.Timeout {
|
|
426
458
|
return setInterval(() => {
|
|
427
459
|
if (this.handleMessageBatch) {
|
|
428
|
-
return this.changeVisibilityTimeoutBatch(
|
|
460
|
+
return this.changeVisibilityTimeoutBatch(
|
|
461
|
+
messages,
|
|
462
|
+
this.visibilityTimeout,
|
|
463
|
+
);
|
|
429
464
|
}
|
|
430
465
|
|
|
431
466
|
return this.changeVisibilityTimeout(message, this.visibilityTimeout);
|
|
@@ -447,7 +482,10 @@ export class Consumer extends TypedEventEmitter {
|
|
|
447
482
|
ReceiptHandle: message.ReceiptHandle,
|
|
448
483
|
VisibilityTimeout: timeout,
|
|
449
484
|
};
|
|
450
|
-
return await this.sqs.send(
|
|
485
|
+
return await this.sqs.send(
|
|
486
|
+
new ChangeMessageVisibilityCommand(input),
|
|
487
|
+
this.sqsSendOptions,
|
|
488
|
+
);
|
|
451
489
|
} catch (err) {
|
|
452
490
|
this.emit(
|
|
453
491
|
"error",
|
|
@@ -555,7 +593,11 @@ export class Consumer extends TypedEventEmitter {
|
|
|
555
593
|
);
|
|
556
594
|
}
|
|
557
595
|
if (err instanceof Error) {
|
|
558
|
-
throw toStandardError(
|
|
596
|
+
throw toStandardError(
|
|
597
|
+
err,
|
|
598
|
+
`Unexpected message handler failure: ${err.message}`,
|
|
599
|
+
message,
|
|
600
|
+
);
|
|
559
601
|
}
|
|
560
602
|
throw err;
|
|
561
603
|
} finally {
|
|
@@ -571,7 +613,8 @@ export class Consumer extends TypedEventEmitter {
|
|
|
571
613
|
*/
|
|
572
614
|
private async executeBatchHandler(messages: Message[]): Promise<Message[]> {
|
|
573
615
|
try {
|
|
574
|
-
const result: Message[] | undefined | null =
|
|
616
|
+
const result: Message[] | undefined | null =
|
|
617
|
+
await this.handleMessageBatch(messages);
|
|
575
618
|
|
|
576
619
|
if (this.alwaysAcknowledge) {
|
|
577
620
|
return messages;
|
|
@@ -618,7 +661,8 @@ export class Consumer extends TypedEventEmitter {
|
|
|
618
661
|
private async deleteMessage(message: Message): Promise<void> {
|
|
619
662
|
if (!this.shouldDeleteMessages) {
|
|
620
663
|
logger.debug("skipping_delete", {
|
|
621
|
-
detail:
|
|
664
|
+
detail:
|
|
665
|
+
"Skipping message delete since shouldDeleteMessages is set to false",
|
|
622
666
|
});
|
|
623
667
|
return;
|
|
624
668
|
}
|
|
@@ -630,7 +674,10 @@ export class Consumer extends TypedEventEmitter {
|
|
|
630
674
|
};
|
|
631
675
|
|
|
632
676
|
try {
|
|
633
|
-
await this.sqs.send(
|
|
677
|
+
await this.sqs.send(
|
|
678
|
+
new DeleteMessageCommand(deleteParams),
|
|
679
|
+
this.sqsSendOptions,
|
|
680
|
+
);
|
|
634
681
|
} catch (err) {
|
|
635
682
|
throw toSQSError(
|
|
636
683
|
err,
|
|
@@ -649,7 +696,8 @@ export class Consumer extends TypedEventEmitter {
|
|
|
649
696
|
private async deleteMessageBatch(messages: Message[]): Promise<void> {
|
|
650
697
|
if (!this.shouldDeleteMessages) {
|
|
651
698
|
logger.debug("skipping_delete", {
|
|
652
|
-
detail:
|
|
699
|
+
detail:
|
|
700
|
+
"Skipping message delete since shouldDeleteMessages is set to false",
|
|
653
701
|
});
|
|
654
702
|
return;
|
|
655
703
|
}
|
|
@@ -666,7 +714,10 @@ export class Consumer extends TypedEventEmitter {
|
|
|
666
714
|
};
|
|
667
715
|
|
|
668
716
|
try {
|
|
669
|
-
await this.sqs.send(
|
|
717
|
+
await this.sqs.send(
|
|
718
|
+
new DeleteMessageBatchCommand(deleteParams),
|
|
719
|
+
this.sqsSendOptions,
|
|
720
|
+
);
|
|
670
721
|
} catch (err) {
|
|
671
722
|
throw toSQSError(
|
|
672
723
|
err,
|
package/src/errors.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
2
|
SQSClient,
|
|
3
3
|
Message,
|
|
4
4
|
QueueAttributeName,
|
|
@@ -72,7 +72,10 @@ export interface ConsumerOptions {
|
|
|
72
72
|
* a number and it will use that as the value for the timeout.
|
|
73
73
|
* @defaultvalue `false`
|
|
74
74
|
*/
|
|
75
|
-
terminateVisibilityTimeout?:
|
|
75
|
+
terminateVisibilityTimeout?:
|
|
76
|
+
| boolean
|
|
77
|
+
| number
|
|
78
|
+
| ((messages: Message[]) => number);
|
|
76
79
|
/**
|
|
77
80
|
* The interval (in seconds) between requests to extend the message visibility timeout.
|
|
78
81
|
*
|
package/src/validation.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ReceiveMessageCommandOutput } from "@aws-sdk/client-sqs";
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { ConsumerOptions } from "./types.js";
|
|
4
4
|
|
|
5
5
|
const requiredOptions = [
|
|
6
6
|
"queueUrl",
|
|
@@ -21,13 +21,23 @@ function validateOption(
|
|
|
21
21
|
}
|
|
22
22
|
break;
|
|
23
23
|
case "heartbeatInterval":
|
|
24
|
-
if (
|
|
25
|
-
|
|
24
|
+
if (
|
|
25
|
+
!allOptions.visibilityTimeout ||
|
|
26
|
+
value >= allOptions.visibilityTimeout
|
|
27
|
+
) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
"heartbeatInterval must be less than visibilityTimeout.",
|
|
30
|
+
);
|
|
26
31
|
}
|
|
27
32
|
break;
|
|
28
33
|
case "visibilityTimeout":
|
|
29
|
-
if (
|
|
30
|
-
|
|
34
|
+
if (
|
|
35
|
+
allOptions.heartbeatInterval &&
|
|
36
|
+
value <= allOptions.heartbeatInterval
|
|
37
|
+
) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
"heartbeatInterval must be less than visibilityTimeout.",
|
|
40
|
+
);
|
|
31
41
|
}
|
|
32
42
|
break;
|
|
33
43
|
case "waitTimeSeconds":
|
|
@@ -56,7 +66,9 @@ function assertOptions(options: ConsumerOptions): void {
|
|
|
56
66
|
requiredOptions.forEach((option) => {
|
|
57
67
|
const possibilities = option.split("|");
|
|
58
68
|
if (!possibilities.find((p) => options[p])) {
|
|
59
|
-
throw new Error(
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Missing SQS consumer option [ ${possibilities.join(" or ")} ].`,
|
|
71
|
+
);
|
|
60
72
|
}
|
|
61
73
|
});
|
|
62
74
|
|
package/.releaserc.json
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"branches": [
|
|
3
|
-
"main",
|
|
4
|
-
"*.x",
|
|
5
|
-
{
|
|
6
|
-
"name": "canary",
|
|
7
|
-
"prerelease": true
|
|
8
|
-
}
|
|
9
|
-
],
|
|
10
|
-
"plugins": [
|
|
11
|
-
[
|
|
12
|
-
"@semantic-release/commit-analyzer",
|
|
13
|
-
{
|
|
14
|
-
"preset": "conventionalcommits",
|
|
15
|
-
"releaseRules": [
|
|
16
|
-
{
|
|
17
|
-
"type": "breaking",
|
|
18
|
-
"release": "major"
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"type": "feat",
|
|
22
|
-
"release": "minor"
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"type": "chore",
|
|
26
|
-
"release": "patch"
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"type": "fix",
|
|
30
|
-
"release": "patch"
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"type": "docs",
|
|
34
|
-
"release": "patch"
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"type": "refactor",
|
|
38
|
-
"release": "patch"
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"type": "test",
|
|
42
|
-
"release": "patch"
|
|
43
|
-
}
|
|
44
|
-
]
|
|
45
|
-
}
|
|
46
|
-
],
|
|
47
|
-
[
|
|
48
|
-
"@semantic-release/release-notes-generator",
|
|
49
|
-
{
|
|
50
|
-
"preset": "conventionalcommits",
|
|
51
|
-
"presetConfig": {
|
|
52
|
-
"types": [
|
|
53
|
-
{
|
|
54
|
-
"type": "feat",
|
|
55
|
-
"section": "Features"
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
"type": "fix",
|
|
59
|
-
"section": "Bug Fixes"
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
"type": "chore",
|
|
63
|
-
"section": "Chores"
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
"type": "docs",
|
|
67
|
-
"section": "Documentation"
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
"type": "refactor",
|
|
71
|
-
"section": "Refactors"
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
"type": "test",
|
|
75
|
-
"section": "Tests"
|
|
76
|
-
}
|
|
77
|
-
]
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
],
|
|
81
|
-
"@semantic-release/changelog",
|
|
82
|
-
"@semantic-release/github",
|
|
83
|
-
"@semantic-release/npm",
|
|
84
|
-
"@sebbo2002/semantic-release-jsr"
|
|
85
|
-
]
|
|
86
|
-
}
|
package/vitest.config.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "vitest/config";
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
environment: "node",
|
|
6
|
-
include: ["test/tests/**/*.test.ts"],
|
|
7
|
-
dangerouslyIgnoreUnhandledErrors: true,
|
|
8
|
-
coverage: {
|
|
9
|
-
provider: "v8",
|
|
10
|
-
include: ["src/**/*.ts"],
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
});
|