@vercel/queue 0.0.0-alpha.5 → 0.0.0-alpha.7
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/README.md +277 -501
- package/dist/index.d.mts +22 -458
- package/dist/index.d.ts +22 -458
- package/dist/index.js +110 -303
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +110 -295
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22,143 +22,97 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
BadRequestError: () => BadRequestError,
|
|
24
24
|
BufferTransport: () => BufferTransport,
|
|
25
|
-
ConsumerGroup: () => ConsumerGroup,
|
|
26
|
-
FailedDependencyError: () => FailedDependencyError,
|
|
27
|
-
FifoOrderingViolationError: () => FifoOrderingViolationError,
|
|
28
25
|
ForbiddenError: () => ForbiddenError,
|
|
29
26
|
InternalServerError: () => InternalServerError,
|
|
30
|
-
InvalidCallbackError: () => InvalidCallbackError,
|
|
31
27
|
InvalidLimitError: () => InvalidLimitError,
|
|
32
28
|
JsonTransport: () => JsonTransport,
|
|
33
29
|
MessageCorruptedError: () => MessageCorruptedError,
|
|
34
30
|
MessageLockedError: () => MessageLockedError,
|
|
35
31
|
MessageNotAvailableError: () => MessageNotAvailableError,
|
|
36
32
|
MessageNotFoundError: () => MessageNotFoundError,
|
|
37
|
-
QueueClient: () => QueueClient,
|
|
38
33
|
QueueEmptyError: () => QueueEmptyError,
|
|
39
34
|
StreamTransport: () => StreamTransport,
|
|
40
|
-
Topic: () => Topic,
|
|
41
35
|
UnauthorizedError: () => UnauthorizedError,
|
|
42
|
-
createTopic: () => createTopic,
|
|
43
36
|
handleCallback: () => handleCallback,
|
|
44
|
-
parseCallbackRequest: () => parseCallbackRequest,
|
|
45
37
|
receive: () => receive,
|
|
46
38
|
send: () => send
|
|
47
39
|
});
|
|
48
40
|
module.exports = __toCommonJS(index_exports);
|
|
49
41
|
|
|
50
|
-
// src/
|
|
51
|
-
var
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
function isLocalhostWithPort(url) {
|
|
56
|
-
try {
|
|
57
|
-
const parsedUrl = new URL(url);
|
|
58
|
-
const isLocalhost = parsedUrl.hostname === "localhost";
|
|
59
|
-
const port = parsedUrl.port ? parseInt(parsedUrl.port, 10) : 0;
|
|
60
|
-
return { isLocalhost, port };
|
|
61
|
-
} catch {
|
|
62
|
-
return { isLocalhost: false };
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
function isSupportedPlatform() {
|
|
66
|
-
const platform = process.platform;
|
|
67
|
-
return platform === "darwin" || platform === "linux";
|
|
68
|
-
}
|
|
69
|
-
function processDevelopmentCallbacks(callbacks) {
|
|
70
|
-
const isDevelopment = process.env.NODE_ENV === "development";
|
|
71
|
-
if (!isDevelopment) {
|
|
72
|
-
return [];
|
|
42
|
+
// src/transports.ts
|
|
43
|
+
var JsonTransport = class {
|
|
44
|
+
contentType = "application/json";
|
|
45
|
+
serialize(value) {
|
|
46
|
+
return Buffer.from(JSON.stringify(value), "utf8");
|
|
73
47
|
}
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
48
|
+
async deserialize(stream) {
|
|
49
|
+
const reader = stream.getReader();
|
|
50
|
+
let totalLength = 0;
|
|
51
|
+
const chunks = [];
|
|
52
|
+
try {
|
|
53
|
+
while (true) {
|
|
54
|
+
const { done, value } = await reader.read();
|
|
55
|
+
if (done) break;
|
|
56
|
+
chunks.push(value);
|
|
57
|
+
totalLength += value.length;
|
|
58
|
+
}
|
|
59
|
+
} finally {
|
|
60
|
+
reader.releaseLock();
|
|
83
61
|
}
|
|
84
|
-
|
|
62
|
+
const buffer = Buffer.concat(chunks, totalLength);
|
|
63
|
+
return JSON.parse(buffer.toString("utf8"));
|
|
85
64
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
65
|
+
};
|
|
66
|
+
var BufferTransport = class {
|
|
67
|
+
contentType = "application/octet-stream";
|
|
68
|
+
serialize(value) {
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
async deserialize(stream) {
|
|
72
|
+
const reader = stream.getReader();
|
|
73
|
+
const chunks = [];
|
|
74
|
+
try {
|
|
75
|
+
while (true) {
|
|
76
|
+
const { done, value } = await reader.read();
|
|
77
|
+
if (done) break;
|
|
78
|
+
chunks.push(value);
|
|
79
|
+
}
|
|
80
|
+
} finally {
|
|
81
|
+
reader.releaseLock();
|
|
95
82
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
callbackHeaders.set("Vqs-Consumer-Group", group);
|
|
105
|
-
fireAndForgetWaitForHttpReady(
|
|
106
|
-
config.url,
|
|
107
|
-
port,
|
|
108
|
-
config.delay || 0,
|
|
109
|
-
3,
|
|
110
|
-
// Default retry frequency
|
|
111
|
-
callbackHeaders
|
|
112
|
-
);
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
function fireAndForgetWaitForHttpReady(url, port, initialDelaySeconds = 0, retryFrequencySeconds = 3, headers) {
|
|
116
|
-
if (!isSupportedPlatform()) {
|
|
117
|
-
console.warn(
|
|
118
|
-
`Queue: fireAndForgetWaitForHttpReady is not supported on ${process.platform}. This function requires bash, nc, and curl which are available on macOS and Linux only.`
|
|
119
|
-
);
|
|
120
|
-
return;
|
|
83
|
+
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
84
|
+
const buffer = new Uint8Array(totalLength);
|
|
85
|
+
let offset = 0;
|
|
86
|
+
for (const chunk of chunks) {
|
|
87
|
+
buffer.set(chunk, offset);
|
|
88
|
+
offset += chunk.length;
|
|
89
|
+
}
|
|
90
|
+
return Buffer.from(buffer);
|
|
121
91
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
});
|
|
128
|
-
headerArgs = headerArray.join(" ");
|
|
92
|
+
};
|
|
93
|
+
var StreamTransport = class {
|
|
94
|
+
contentType = "application/octet-stream";
|
|
95
|
+
serialize(value) {
|
|
96
|
+
return value;
|
|
129
97
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
98
|
+
async deserialize(stream) {
|
|
99
|
+
return stream;
|
|
100
|
+
}
|
|
101
|
+
async finalize(payload) {
|
|
102
|
+
const reader = payload.getReader();
|
|
103
|
+
try {
|
|
104
|
+
while (true) {
|
|
105
|
+
const { done } = await reader.read();
|
|
106
|
+
if (done) break;
|
|
107
|
+
}
|
|
108
|
+
} finally {
|
|
109
|
+
reader.releaseLock();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
133
113
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
# 1) Check if TCP port is listening
|
|
137
|
-
if nc -z localhost ${port} 2>/dev/null; then
|
|
138
|
-
missed=0
|
|
139
|
-
# 2) If port is open, try HTTP POST check
|
|
140
|
-
if curl -sSL --fail -o /dev/null -X POST ${headerArgs} "${url}"; then
|
|
141
|
-
# Success: port is up AND HTTP returned 2xx (following redirects)
|
|
142
|
-
exit 0
|
|
143
|
-
fi
|
|
144
|
-
else
|
|
145
|
-
# Port was closed\u2014increment miss counter
|
|
146
|
-
((missed+=1))
|
|
147
|
-
# If closed twice in a row, give up immediately
|
|
148
|
-
if [ "$missed" -ge 2 ]; then
|
|
149
|
-
exit 1
|
|
150
|
-
fi
|
|
151
|
-
fi
|
|
152
|
-
# Wait before next cycle
|
|
153
|
-
sleep ${retryFrequencySeconds}
|
|
154
|
-
done
|
|
155
|
-
`;
|
|
156
|
-
const childProcess = (0, import_node_child_process.spawn)("bash", ["-c", bashScript], {
|
|
157
|
-
stdio: "ignore",
|
|
158
|
-
detached: true
|
|
159
|
-
});
|
|
160
|
-
childProcess.unref();
|
|
161
|
-
}
|
|
114
|
+
// src/client.ts
|
|
115
|
+
var import_mixpart = require("mixpart");
|
|
162
116
|
|
|
163
117
|
// src/types.ts
|
|
164
118
|
var MessageNotFoundError = class extends Error {
|
|
@@ -175,12 +129,6 @@ var MessageNotAvailableError = class extends Error {
|
|
|
175
129
|
this.name = "MessageNotAvailableError";
|
|
176
130
|
}
|
|
177
131
|
};
|
|
178
|
-
var FifoOrderingViolationError = class extends Error {
|
|
179
|
-
constructor(messageId, reason) {
|
|
180
|
-
super(`FIFO ordering violation for message ${messageId}: ${reason}`);
|
|
181
|
-
this.name = "FifoOrderingViolationError";
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
132
|
var MessageCorruptedError = class extends Error {
|
|
185
133
|
constructor(messageId, reason) {
|
|
186
134
|
super(`Message ${messageId} is corrupted: ${reason}`);
|
|
@@ -222,14 +170,6 @@ var BadRequestError = class extends Error {
|
|
|
222
170
|
this.name = "BadRequestError";
|
|
223
171
|
}
|
|
224
172
|
};
|
|
225
|
-
var FailedDependencyError = class extends Error {
|
|
226
|
-
constructor(messageId) {
|
|
227
|
-
super(
|
|
228
|
-
`Failed dependency: FIFO ordering violation for message ${messageId}`
|
|
229
|
-
);
|
|
230
|
-
this.name = "FailedDependencyError";
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
173
|
var InternalServerError = class extends Error {
|
|
234
174
|
constructor(message = "Unexpected server error") {
|
|
235
175
|
super(message);
|
|
@@ -242,12 +182,6 @@ var InvalidLimitError = class extends Error {
|
|
|
242
182
|
this.name = "InvalidLimitError";
|
|
243
183
|
}
|
|
244
184
|
};
|
|
245
|
-
var InvalidCallbackError = class extends Error {
|
|
246
|
-
constructor(message) {
|
|
247
|
-
super(message);
|
|
248
|
-
this.name = "InvalidCallbackError";
|
|
249
|
-
}
|
|
250
|
-
};
|
|
251
185
|
|
|
252
186
|
// src/client.ts
|
|
253
187
|
async function consumeStream(stream) {
|
|
@@ -286,7 +220,7 @@ var QueueClient = class _QueueClient {
|
|
|
286
220
|
baseUrl;
|
|
287
221
|
token;
|
|
288
222
|
/**
|
|
289
|
-
* Internal default instance for use by
|
|
223
|
+
* Internal default instance for use by convenience functions
|
|
290
224
|
* @internal
|
|
291
225
|
*/
|
|
292
226
|
static _defaultInstance = null;
|
|
@@ -344,7 +278,7 @@ var QueueClient = class _QueueClient {
|
|
|
344
278
|
* @throws {InternalServerError} When server encounters an error
|
|
345
279
|
*/
|
|
346
280
|
async sendMessage(options, transport) {
|
|
347
|
-
const { queueName, payload, idempotencyKey, retentionSeconds
|
|
281
|
+
const { queueName, payload, idempotencyKey, retentionSeconds } = options;
|
|
348
282
|
const headers = new Headers({
|
|
349
283
|
Authorization: `Bearer ${this.token}`,
|
|
350
284
|
"Vqs-Queue-Name": queueName,
|
|
@@ -359,34 +293,6 @@ var QueueClient = class _QueueClient {
|
|
|
359
293
|
if (retentionSeconds !== void 0) {
|
|
360
294
|
headers.set("Vqs-Retention-Seconds", retentionSeconds.toString());
|
|
361
295
|
}
|
|
362
|
-
let normalizedCallbacks;
|
|
363
|
-
if (callback) {
|
|
364
|
-
if ("url" in callback && typeof callback.url === "string") {
|
|
365
|
-
normalizedCallbacks = { default: callback };
|
|
366
|
-
} else {
|
|
367
|
-
normalizedCallbacks = callback;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
let localhostCallbacks = [];
|
|
371
|
-
if (normalizedCallbacks) {
|
|
372
|
-
const isDevelopment = process.env.NODE_ENV === "development";
|
|
373
|
-
if (isDevelopment) {
|
|
374
|
-
localhostCallbacks = processDevelopmentCallbacks(normalizedCallbacks);
|
|
375
|
-
} else {
|
|
376
|
-
const endpoints = Object.entries(normalizedCallbacks).map(
|
|
377
|
-
([group, config]) => `${group}=${Buffer.from(config.url).toString("base64")}`
|
|
378
|
-
).join(",");
|
|
379
|
-
headers.set("Vqs-Callback-Url", endpoints);
|
|
380
|
-
const delays = Object.entries(normalizedCallbacks).filter(([, config]) => config.delay !== void 0).map(([group, config]) => `${group}=${config.delay}`).join(",");
|
|
381
|
-
if (delays) {
|
|
382
|
-
headers.set("Vqs-Callback-Delay", delays);
|
|
383
|
-
}
|
|
384
|
-
const frequencies = Object.entries(normalizedCallbacks).filter(([, config]) => config.frequency !== void 0).map(([group, config]) => `${group}=${config.frequency}`).join(",");
|
|
385
|
-
if (frequencies) {
|
|
386
|
-
headers.set("Vqs-Callback-Frequency", frequencies);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
296
|
const body = transport.serialize(payload);
|
|
391
297
|
const response = await fetch(`${this.baseUrl}/api/v2/messages`, {
|
|
392
298
|
method: "POST",
|
|
@@ -417,9 +323,6 @@ var QueueClient = class _QueueClient {
|
|
|
417
323
|
);
|
|
418
324
|
}
|
|
419
325
|
const responseData = await response.json();
|
|
420
|
-
if (localhostCallbacks.length > 0) {
|
|
421
|
-
fireLocalhostCallbacks(localhostCallbacks, queueName, responseData);
|
|
422
|
-
}
|
|
423
326
|
return responseData;
|
|
424
327
|
}
|
|
425
328
|
/**
|
|
@@ -429,7 +332,7 @@ var QueueClient = class _QueueClient {
|
|
|
429
332
|
* @returns AsyncGenerator that yields messages as they arrive
|
|
430
333
|
* @throws {InvalidLimitError} When limit parameter is not between 1 and 10
|
|
431
334
|
* @throws {QueueEmptyError} When no messages are available (204)
|
|
432
|
-
* @throws {MessageLockedError} When
|
|
335
|
+
* @throws {MessageLockedError} When messages are temporarily locked (423)
|
|
433
336
|
* @throws {BadRequestError} When request parameters are invalid
|
|
434
337
|
* @throws {UnauthorizedError} When authentication fails
|
|
435
338
|
* @throws {ForbiddenError} When access is denied (environment mismatch)
|
|
@@ -480,7 +383,7 @@ var QueueClient = class _QueueClient {
|
|
|
480
383
|
const parsed = parseInt(retryAfterHeader, 10);
|
|
481
384
|
retryAfter = isNaN(parsed) ? void 0 : parsed;
|
|
482
385
|
}
|
|
483
|
-
throw new MessageLockedError("next message
|
|
386
|
+
throw new MessageLockedError("next message", retryAfter);
|
|
484
387
|
}
|
|
485
388
|
if (response.status >= 500) {
|
|
486
389
|
throw new InternalServerError(
|
|
@@ -566,9 +469,6 @@ var QueueClient = class _QueueClient {
|
|
|
566
469
|
}
|
|
567
470
|
throw new MessageLockedError(messageId, retryAfter);
|
|
568
471
|
}
|
|
569
|
-
if (response.status === 424) {
|
|
570
|
-
throw new FailedDependencyError(messageId);
|
|
571
|
-
}
|
|
572
472
|
if (response.status === 409) {
|
|
573
473
|
throw new MessageNotAvailableError(messageId);
|
|
574
474
|
}
|
|
@@ -756,82 +656,6 @@ var QueueClient = class _QueueClient {
|
|
|
756
656
|
}
|
|
757
657
|
};
|
|
758
658
|
|
|
759
|
-
// src/transports.ts
|
|
760
|
-
var JsonTransport = class {
|
|
761
|
-
contentType = "application/json";
|
|
762
|
-
serialize(value) {
|
|
763
|
-
return Buffer.from(JSON.stringify(value), "utf8");
|
|
764
|
-
}
|
|
765
|
-
async deserialize(stream) {
|
|
766
|
-
const reader = stream.getReader();
|
|
767
|
-
const chunks = [];
|
|
768
|
-
try {
|
|
769
|
-
while (true) {
|
|
770
|
-
const { done, value } = await reader.read();
|
|
771
|
-
if (done) break;
|
|
772
|
-
chunks.push(value);
|
|
773
|
-
}
|
|
774
|
-
} finally {
|
|
775
|
-
reader.releaseLock();
|
|
776
|
-
}
|
|
777
|
-
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
778
|
-
const buffer = new Uint8Array(totalLength);
|
|
779
|
-
let offset = 0;
|
|
780
|
-
for (const chunk of chunks) {
|
|
781
|
-
buffer.set(chunk, offset);
|
|
782
|
-
offset += chunk.length;
|
|
783
|
-
}
|
|
784
|
-
return JSON.parse(Buffer.from(buffer).toString("utf8"));
|
|
785
|
-
}
|
|
786
|
-
};
|
|
787
|
-
var BufferTransport = class {
|
|
788
|
-
contentType = "application/octet-stream";
|
|
789
|
-
serialize(value) {
|
|
790
|
-
return value;
|
|
791
|
-
}
|
|
792
|
-
async deserialize(stream) {
|
|
793
|
-
const reader = stream.getReader();
|
|
794
|
-
const chunks = [];
|
|
795
|
-
try {
|
|
796
|
-
while (true) {
|
|
797
|
-
const { done, value } = await reader.read();
|
|
798
|
-
if (done) break;
|
|
799
|
-
chunks.push(value);
|
|
800
|
-
}
|
|
801
|
-
} finally {
|
|
802
|
-
reader.releaseLock();
|
|
803
|
-
}
|
|
804
|
-
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
805
|
-
const buffer = new Uint8Array(totalLength);
|
|
806
|
-
let offset = 0;
|
|
807
|
-
for (const chunk of chunks) {
|
|
808
|
-
buffer.set(chunk, offset);
|
|
809
|
-
offset += chunk.length;
|
|
810
|
-
}
|
|
811
|
-
return Buffer.from(buffer);
|
|
812
|
-
}
|
|
813
|
-
};
|
|
814
|
-
var StreamTransport = class {
|
|
815
|
-
contentType = "application/octet-stream";
|
|
816
|
-
serialize(value) {
|
|
817
|
-
return value;
|
|
818
|
-
}
|
|
819
|
-
async deserialize(stream) {
|
|
820
|
-
return stream;
|
|
821
|
-
}
|
|
822
|
-
async finalize(payload) {
|
|
823
|
-
const reader = payload.getReader();
|
|
824
|
-
try {
|
|
825
|
-
while (true) {
|
|
826
|
-
const { done } = await reader.read();
|
|
827
|
-
if (done) break;
|
|
828
|
-
}
|
|
829
|
-
} finally {
|
|
830
|
-
reader.releaseLock();
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
};
|
|
834
|
-
|
|
835
659
|
// src/consumer-group.ts
|
|
836
660
|
var ConsumerGroup = class {
|
|
837
661
|
client;
|
|
@@ -1063,8 +887,7 @@ var Topic = class {
|
|
|
1063
887
|
queueName: this.topicName,
|
|
1064
888
|
payload,
|
|
1065
889
|
idempotencyKey: options?.idempotencyKey,
|
|
1066
|
-
retentionSeconds: options?.retentionSeconds
|
|
1067
|
-
callback: options?.callback
|
|
890
|
+
retentionSeconds: options?.retentionSeconds
|
|
1068
891
|
},
|
|
1069
892
|
this.transport
|
|
1070
893
|
);
|
|
@@ -1103,10 +926,6 @@ var Topic = class {
|
|
|
1103
926
|
};
|
|
1104
927
|
|
|
1105
928
|
// src/factory.ts
|
|
1106
|
-
function createTopic(topicName, transport) {
|
|
1107
|
-
const client = QueueClient._getDefaultInstance();
|
|
1108
|
-
return new Topic(client, topicName, transport);
|
|
1109
|
-
}
|
|
1110
929
|
async function send(topicName, payload, options) {
|
|
1111
930
|
const transport = options?.transport || new JsonTransport();
|
|
1112
931
|
const client = QueueClient._getDefaultInstance();
|
|
@@ -1115,8 +934,7 @@ async function send(topicName, payload, options) {
|
|
|
1115
934
|
queueName: topicName,
|
|
1116
935
|
payload,
|
|
1117
936
|
idempotencyKey: options?.idempotencyKey,
|
|
1118
|
-
retentionSeconds: options?.retentionSeconds
|
|
1119
|
-
callback: options?.callback
|
|
937
|
+
retentionSeconds: options?.retentionSeconds
|
|
1120
938
|
},
|
|
1121
939
|
transport
|
|
1122
940
|
);
|
|
@@ -1124,7 +942,8 @@ async function send(topicName, payload, options) {
|
|
|
1124
942
|
}
|
|
1125
943
|
async function receive(topicName, consumerGroup, handler, options) {
|
|
1126
944
|
const transport = options?.transport || new JsonTransport();
|
|
1127
|
-
const
|
|
945
|
+
const client = QueueClient._getDefaultInstance();
|
|
946
|
+
const topic = new Topic(client, topicName, transport);
|
|
1128
947
|
const { messageId, skipPayload, ...consumerGroupOptions } = options || {};
|
|
1129
948
|
const consumer = topic.consumerGroup(consumerGroup, consumerGroupOptions);
|
|
1130
949
|
if (messageId) {
|
|
@@ -1143,23 +962,22 @@ async function receive(topicName, consumerGroup, handler, options) {
|
|
|
1143
962
|
|
|
1144
963
|
// src/callback.ts
|
|
1145
964
|
function parseCallbackRequest(request) {
|
|
1146
|
-
const
|
|
1147
|
-
const
|
|
1148
|
-
const
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
`Missing required queue callback headers: ${missingHeaders.join(", ")}`
|
|
965
|
+
const queueName = request.headers.get("Vqs-Queue-Name");
|
|
966
|
+
const consumerGroup = request.headers.get("Vqs-Consumer-Group");
|
|
967
|
+
const messageId = request.headers.get("Vqs-Message-Id");
|
|
968
|
+
if (!queueName || !consumerGroup || !messageId) {
|
|
969
|
+
const missingHeaders = [];
|
|
970
|
+
if (!queueName) missingHeaders.push("Vqs-Queue-Name");
|
|
971
|
+
if (!consumerGroup) missingHeaders.push("Vqs-Consumer-Group");
|
|
972
|
+
if (!messageId) missingHeaders.push("Vqs-Message-Id");
|
|
973
|
+
throw new Error(
|
|
974
|
+
`Missing required queue headers: ${missingHeaders.join(", ")}`
|
|
1157
975
|
);
|
|
1158
976
|
}
|
|
1159
977
|
return {
|
|
1160
|
-
messageId,
|
|
1161
978
|
queueName,
|
|
1162
|
-
consumerGroup
|
|
979
|
+
consumerGroup,
|
|
980
|
+
messageId
|
|
1163
981
|
};
|
|
1164
982
|
}
|
|
1165
983
|
function handleCallback(handlers) {
|
|
@@ -1168,41 +986,38 @@ function handleCallback(handlers) {
|
|
|
1168
986
|
const { queueName, consumerGroup, messageId } = parseCallbackRequest(request);
|
|
1169
987
|
const topicHandler = handlers[queueName];
|
|
1170
988
|
if (!topicHandler) {
|
|
1171
|
-
|
|
989
|
+
const availableTopics = Object.keys(handlers).join(", ");
|
|
990
|
+
return Response.json(
|
|
991
|
+
{
|
|
992
|
+
error: `No handler found for topic: ${queueName}`,
|
|
993
|
+
availableTopics
|
|
994
|
+
},
|
|
995
|
+
{ status: 404 }
|
|
996
|
+
);
|
|
1172
997
|
}
|
|
1173
|
-
|
|
1174
|
-
if (
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
if (!consumerGroupHandler) {
|
|
1184
|
-
const availableGroups = Object.keys(topicHandler).join(", ");
|
|
1185
|
-
throw new Error(
|
|
1186
|
-
`No handler found for consumer group "${consumerGroup}" in topic "${queueName}". Available groups: ${availableGroups}`
|
|
1187
|
-
);
|
|
1188
|
-
}
|
|
1189
|
-
actualHandler = consumerGroupHandler;
|
|
998
|
+
const consumerGroupHandler = topicHandler[consumerGroup];
|
|
999
|
+
if (!consumerGroupHandler) {
|
|
1000
|
+
const availableGroups = Object.keys(topicHandler).join(", ");
|
|
1001
|
+
return Response.json(
|
|
1002
|
+
{
|
|
1003
|
+
error: `No handler found for consumer group "${consumerGroup}" in topic "${queueName}".`,
|
|
1004
|
+
availableGroups
|
|
1005
|
+
},
|
|
1006
|
+
{ status: 404 }
|
|
1007
|
+
);
|
|
1190
1008
|
}
|
|
1191
1009
|
const client = new QueueClient();
|
|
1192
1010
|
const topic = new Topic(client, queueName);
|
|
1193
1011
|
const cg = topic.consumerGroup(consumerGroup);
|
|
1194
|
-
await cg.consume(
|
|
1012
|
+
await cg.consume(consumerGroupHandler, { messageId });
|
|
1195
1013
|
return Response.json({ status: "success" });
|
|
1196
1014
|
} catch (error) {
|
|
1197
|
-
console.error("
|
|
1198
|
-
if (error instanceof
|
|
1199
|
-
return Response.json(
|
|
1200
|
-
{ error: "Invalid callback request" },
|
|
1201
|
-
{ status: 400 }
|
|
1202
|
-
);
|
|
1015
|
+
console.error("Queue callback error:", error);
|
|
1016
|
+
if (error instanceof Error && error.message.includes("Missing required queue headers")) {
|
|
1017
|
+
return Response.json({ error: error.message }, { status: 400 });
|
|
1203
1018
|
}
|
|
1204
1019
|
return Response.json(
|
|
1205
|
-
{ error: "Failed to process
|
|
1020
|
+
{ error: "Failed to process queue message" },
|
|
1206
1021
|
{ status: 500 }
|
|
1207
1022
|
);
|
|
1208
1023
|
}
|
|
@@ -1212,26 +1027,18 @@ function handleCallback(handlers) {
|
|
|
1212
1027
|
0 && (module.exports = {
|
|
1213
1028
|
BadRequestError,
|
|
1214
1029
|
BufferTransport,
|
|
1215
|
-
ConsumerGroup,
|
|
1216
|
-
FailedDependencyError,
|
|
1217
|
-
FifoOrderingViolationError,
|
|
1218
1030
|
ForbiddenError,
|
|
1219
1031
|
InternalServerError,
|
|
1220
|
-
InvalidCallbackError,
|
|
1221
1032
|
InvalidLimitError,
|
|
1222
1033
|
JsonTransport,
|
|
1223
1034
|
MessageCorruptedError,
|
|
1224
1035
|
MessageLockedError,
|
|
1225
1036
|
MessageNotAvailableError,
|
|
1226
1037
|
MessageNotFoundError,
|
|
1227
|
-
QueueClient,
|
|
1228
1038
|
QueueEmptyError,
|
|
1229
1039
|
StreamTransport,
|
|
1230
|
-
Topic,
|
|
1231
1040
|
UnauthorizedError,
|
|
1232
|
-
createTopic,
|
|
1233
1041
|
handleCallback,
|
|
1234
|
-
parseCallbackRequest,
|
|
1235
1042
|
receive,
|
|
1236
1043
|
send
|
|
1237
1044
|
});
|