@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.mjs
CHANGED
|
@@ -1,115 +1,77 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
function isLocalhostWithPort(url) {
|
|
7
|
-
try {
|
|
8
|
-
const parsedUrl = new URL(url);
|
|
9
|
-
const isLocalhost = parsedUrl.hostname === "localhost";
|
|
10
|
-
const port = parsedUrl.port ? parseInt(parsedUrl.port, 10) : 0;
|
|
11
|
-
return { isLocalhost, port };
|
|
12
|
-
} catch {
|
|
13
|
-
return { isLocalhost: false };
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
function isSupportedPlatform() {
|
|
17
|
-
const platform = process.platform;
|
|
18
|
-
return platform === "darwin" || platform === "linux";
|
|
19
|
-
}
|
|
20
|
-
function processDevelopmentCallbacks(callbacks) {
|
|
21
|
-
const isDevelopment = process.env.NODE_ENV === "development";
|
|
22
|
-
if (!isDevelopment) {
|
|
23
|
-
return [];
|
|
1
|
+
// src/transports.ts
|
|
2
|
+
var JsonTransport = class {
|
|
3
|
+
contentType = "application/json";
|
|
4
|
+
serialize(value) {
|
|
5
|
+
return Buffer.from(JSON.stringify(value), "utf8");
|
|
24
6
|
}
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
7
|
+
async deserialize(stream) {
|
|
8
|
+
const reader = stream.getReader();
|
|
9
|
+
let totalLength = 0;
|
|
10
|
+
const chunks = [];
|
|
11
|
+
try {
|
|
12
|
+
while (true) {
|
|
13
|
+
const { done, value } = await reader.read();
|
|
14
|
+
if (done) break;
|
|
15
|
+
chunks.push(value);
|
|
16
|
+
totalLength += value.length;
|
|
17
|
+
}
|
|
18
|
+
} finally {
|
|
19
|
+
reader.releaseLock();
|
|
34
20
|
}
|
|
35
|
-
|
|
21
|
+
const buffer = Buffer.concat(chunks, totalLength);
|
|
22
|
+
return JSON.parse(buffer.toString("utf8"));
|
|
36
23
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
24
|
+
};
|
|
25
|
+
var BufferTransport = class {
|
|
26
|
+
contentType = "application/octet-stream";
|
|
27
|
+
serialize(value) {
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
async deserialize(stream) {
|
|
31
|
+
const reader = stream.getReader();
|
|
32
|
+
const chunks = [];
|
|
33
|
+
try {
|
|
34
|
+
while (true) {
|
|
35
|
+
const { done, value } = await reader.read();
|
|
36
|
+
if (done) break;
|
|
37
|
+
chunks.push(value);
|
|
38
|
+
}
|
|
39
|
+
} finally {
|
|
40
|
+
reader.releaseLock();
|
|
46
41
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
callbackHeaders.set("Vqs-Consumer-Group", group);
|
|
56
|
-
fireAndForgetWaitForHttpReady(
|
|
57
|
-
config.url,
|
|
58
|
-
port,
|
|
59
|
-
config.delay || 0,
|
|
60
|
-
3,
|
|
61
|
-
// Default retry frequency
|
|
62
|
-
callbackHeaders
|
|
63
|
-
);
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
function fireAndForgetWaitForHttpReady(url, port, initialDelaySeconds = 0, retryFrequencySeconds = 3, headers) {
|
|
67
|
-
if (!isSupportedPlatform()) {
|
|
68
|
-
console.warn(
|
|
69
|
-
`Queue: fireAndForgetWaitForHttpReady is not supported on ${process.platform}. This function requires bash, nc, and curl which are available on macOS and Linux only.`
|
|
70
|
-
);
|
|
71
|
-
return;
|
|
42
|
+
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
43
|
+
const buffer = new Uint8Array(totalLength);
|
|
44
|
+
let offset = 0;
|
|
45
|
+
for (const chunk of chunks) {
|
|
46
|
+
buffer.set(chunk, offset);
|
|
47
|
+
offset += chunk.length;
|
|
48
|
+
}
|
|
49
|
+
return Buffer.from(buffer);
|
|
72
50
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
});
|
|
79
|
-
headerArgs = headerArray.join(" ");
|
|
51
|
+
};
|
|
52
|
+
var StreamTransport = class {
|
|
53
|
+
contentType = "application/octet-stream";
|
|
54
|
+
serialize(value) {
|
|
55
|
+
return value;
|
|
80
56
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
57
|
+
async deserialize(stream) {
|
|
58
|
+
return stream;
|
|
59
|
+
}
|
|
60
|
+
async finalize(payload) {
|
|
61
|
+
const reader = payload.getReader();
|
|
62
|
+
try {
|
|
63
|
+
while (true) {
|
|
64
|
+
const { done } = await reader.read();
|
|
65
|
+
if (done) break;
|
|
66
|
+
}
|
|
67
|
+
} finally {
|
|
68
|
+
reader.releaseLock();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
84
72
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
# 1) Check if TCP port is listening
|
|
88
|
-
if nc -z localhost ${port} 2>/dev/null; then
|
|
89
|
-
missed=0
|
|
90
|
-
# 2) If port is open, try HTTP POST check
|
|
91
|
-
if curl -sSL --fail -o /dev/null -X POST ${headerArgs} "${url}"; then
|
|
92
|
-
# Success: port is up AND HTTP returned 2xx (following redirects)
|
|
93
|
-
exit 0
|
|
94
|
-
fi
|
|
95
|
-
else
|
|
96
|
-
# Port was closed\u2014increment miss counter
|
|
97
|
-
((missed+=1))
|
|
98
|
-
# If closed twice in a row, give up immediately
|
|
99
|
-
if [ "$missed" -ge 2 ]; then
|
|
100
|
-
exit 1
|
|
101
|
-
fi
|
|
102
|
-
fi
|
|
103
|
-
# Wait before next cycle
|
|
104
|
-
sleep ${retryFrequencySeconds}
|
|
105
|
-
done
|
|
106
|
-
`;
|
|
107
|
-
const childProcess = spawn("bash", ["-c", bashScript], {
|
|
108
|
-
stdio: "ignore",
|
|
109
|
-
detached: true
|
|
110
|
-
});
|
|
111
|
-
childProcess.unref();
|
|
112
|
-
}
|
|
73
|
+
// src/client.ts
|
|
74
|
+
import { parseMultipartStream } from "mixpart";
|
|
113
75
|
|
|
114
76
|
// src/types.ts
|
|
115
77
|
var MessageNotFoundError = class extends Error {
|
|
@@ -126,12 +88,6 @@ var MessageNotAvailableError = class extends Error {
|
|
|
126
88
|
this.name = "MessageNotAvailableError";
|
|
127
89
|
}
|
|
128
90
|
};
|
|
129
|
-
var FifoOrderingViolationError = class extends Error {
|
|
130
|
-
constructor(messageId, reason) {
|
|
131
|
-
super(`FIFO ordering violation for message ${messageId}: ${reason}`);
|
|
132
|
-
this.name = "FifoOrderingViolationError";
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
91
|
var MessageCorruptedError = class extends Error {
|
|
136
92
|
constructor(messageId, reason) {
|
|
137
93
|
super(`Message ${messageId} is corrupted: ${reason}`);
|
|
@@ -173,14 +129,6 @@ var BadRequestError = class extends Error {
|
|
|
173
129
|
this.name = "BadRequestError";
|
|
174
130
|
}
|
|
175
131
|
};
|
|
176
|
-
var FailedDependencyError = class extends Error {
|
|
177
|
-
constructor(messageId) {
|
|
178
|
-
super(
|
|
179
|
-
`Failed dependency: FIFO ordering violation for message ${messageId}`
|
|
180
|
-
);
|
|
181
|
-
this.name = "FailedDependencyError";
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
132
|
var InternalServerError = class extends Error {
|
|
185
133
|
constructor(message = "Unexpected server error") {
|
|
186
134
|
super(message);
|
|
@@ -193,12 +141,6 @@ var InvalidLimitError = class extends Error {
|
|
|
193
141
|
this.name = "InvalidLimitError";
|
|
194
142
|
}
|
|
195
143
|
};
|
|
196
|
-
var InvalidCallbackError = class extends Error {
|
|
197
|
-
constructor(message) {
|
|
198
|
-
super(message);
|
|
199
|
-
this.name = "InvalidCallbackError";
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
144
|
|
|
203
145
|
// src/client.ts
|
|
204
146
|
async function consumeStream(stream) {
|
|
@@ -237,7 +179,7 @@ var QueueClient = class _QueueClient {
|
|
|
237
179
|
baseUrl;
|
|
238
180
|
token;
|
|
239
181
|
/**
|
|
240
|
-
* Internal default instance for use by
|
|
182
|
+
* Internal default instance for use by convenience functions
|
|
241
183
|
* @internal
|
|
242
184
|
*/
|
|
243
185
|
static _defaultInstance = null;
|
|
@@ -295,7 +237,7 @@ var QueueClient = class _QueueClient {
|
|
|
295
237
|
* @throws {InternalServerError} When server encounters an error
|
|
296
238
|
*/
|
|
297
239
|
async sendMessage(options, transport) {
|
|
298
|
-
const { queueName, payload, idempotencyKey, retentionSeconds
|
|
240
|
+
const { queueName, payload, idempotencyKey, retentionSeconds } = options;
|
|
299
241
|
const headers = new Headers({
|
|
300
242
|
Authorization: `Bearer ${this.token}`,
|
|
301
243
|
"Vqs-Queue-Name": queueName,
|
|
@@ -310,34 +252,6 @@ var QueueClient = class _QueueClient {
|
|
|
310
252
|
if (retentionSeconds !== void 0) {
|
|
311
253
|
headers.set("Vqs-Retention-Seconds", retentionSeconds.toString());
|
|
312
254
|
}
|
|
313
|
-
let normalizedCallbacks;
|
|
314
|
-
if (callback) {
|
|
315
|
-
if ("url" in callback && typeof callback.url === "string") {
|
|
316
|
-
normalizedCallbacks = { default: callback };
|
|
317
|
-
} else {
|
|
318
|
-
normalizedCallbacks = callback;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
let localhostCallbacks = [];
|
|
322
|
-
if (normalizedCallbacks) {
|
|
323
|
-
const isDevelopment = process.env.NODE_ENV === "development";
|
|
324
|
-
if (isDevelopment) {
|
|
325
|
-
localhostCallbacks = processDevelopmentCallbacks(normalizedCallbacks);
|
|
326
|
-
} else {
|
|
327
|
-
const endpoints = Object.entries(normalizedCallbacks).map(
|
|
328
|
-
([group, config]) => `${group}=${Buffer.from(config.url).toString("base64")}`
|
|
329
|
-
).join(",");
|
|
330
|
-
headers.set("Vqs-Callback-Url", endpoints);
|
|
331
|
-
const delays = Object.entries(normalizedCallbacks).filter(([, config]) => config.delay !== void 0).map(([group, config]) => `${group}=${config.delay}`).join(",");
|
|
332
|
-
if (delays) {
|
|
333
|
-
headers.set("Vqs-Callback-Delay", delays);
|
|
334
|
-
}
|
|
335
|
-
const frequencies = Object.entries(normalizedCallbacks).filter(([, config]) => config.frequency !== void 0).map(([group, config]) => `${group}=${config.frequency}`).join(",");
|
|
336
|
-
if (frequencies) {
|
|
337
|
-
headers.set("Vqs-Callback-Frequency", frequencies);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
255
|
const body = transport.serialize(payload);
|
|
342
256
|
const response = await fetch(`${this.baseUrl}/api/v2/messages`, {
|
|
343
257
|
method: "POST",
|
|
@@ -368,9 +282,6 @@ var QueueClient = class _QueueClient {
|
|
|
368
282
|
);
|
|
369
283
|
}
|
|
370
284
|
const responseData = await response.json();
|
|
371
|
-
if (localhostCallbacks.length > 0) {
|
|
372
|
-
fireLocalhostCallbacks(localhostCallbacks, queueName, responseData);
|
|
373
|
-
}
|
|
374
285
|
return responseData;
|
|
375
286
|
}
|
|
376
287
|
/**
|
|
@@ -380,7 +291,7 @@ var QueueClient = class _QueueClient {
|
|
|
380
291
|
* @returns AsyncGenerator that yields messages as they arrive
|
|
381
292
|
* @throws {InvalidLimitError} When limit parameter is not between 1 and 10
|
|
382
293
|
* @throws {QueueEmptyError} When no messages are available (204)
|
|
383
|
-
* @throws {MessageLockedError} When
|
|
294
|
+
* @throws {MessageLockedError} When messages are temporarily locked (423)
|
|
384
295
|
* @throws {BadRequestError} When request parameters are invalid
|
|
385
296
|
* @throws {UnauthorizedError} When authentication fails
|
|
386
297
|
* @throws {ForbiddenError} When access is denied (environment mismatch)
|
|
@@ -431,7 +342,7 @@ var QueueClient = class _QueueClient {
|
|
|
431
342
|
const parsed = parseInt(retryAfterHeader, 10);
|
|
432
343
|
retryAfter = isNaN(parsed) ? void 0 : parsed;
|
|
433
344
|
}
|
|
434
|
-
throw new MessageLockedError("next message
|
|
345
|
+
throw new MessageLockedError("next message", retryAfter);
|
|
435
346
|
}
|
|
436
347
|
if (response.status >= 500) {
|
|
437
348
|
throw new InternalServerError(
|
|
@@ -517,9 +428,6 @@ var QueueClient = class _QueueClient {
|
|
|
517
428
|
}
|
|
518
429
|
throw new MessageLockedError(messageId, retryAfter);
|
|
519
430
|
}
|
|
520
|
-
if (response.status === 424) {
|
|
521
|
-
throw new FailedDependencyError(messageId);
|
|
522
|
-
}
|
|
523
431
|
if (response.status === 409) {
|
|
524
432
|
throw new MessageNotAvailableError(messageId);
|
|
525
433
|
}
|
|
@@ -707,82 +615,6 @@ var QueueClient = class _QueueClient {
|
|
|
707
615
|
}
|
|
708
616
|
};
|
|
709
617
|
|
|
710
|
-
// src/transports.ts
|
|
711
|
-
var JsonTransport = class {
|
|
712
|
-
contentType = "application/json";
|
|
713
|
-
serialize(value) {
|
|
714
|
-
return Buffer.from(JSON.stringify(value), "utf8");
|
|
715
|
-
}
|
|
716
|
-
async deserialize(stream) {
|
|
717
|
-
const reader = stream.getReader();
|
|
718
|
-
const chunks = [];
|
|
719
|
-
try {
|
|
720
|
-
while (true) {
|
|
721
|
-
const { done, value } = await reader.read();
|
|
722
|
-
if (done) break;
|
|
723
|
-
chunks.push(value);
|
|
724
|
-
}
|
|
725
|
-
} finally {
|
|
726
|
-
reader.releaseLock();
|
|
727
|
-
}
|
|
728
|
-
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
729
|
-
const buffer = new Uint8Array(totalLength);
|
|
730
|
-
let offset = 0;
|
|
731
|
-
for (const chunk of chunks) {
|
|
732
|
-
buffer.set(chunk, offset);
|
|
733
|
-
offset += chunk.length;
|
|
734
|
-
}
|
|
735
|
-
return JSON.parse(Buffer.from(buffer).toString("utf8"));
|
|
736
|
-
}
|
|
737
|
-
};
|
|
738
|
-
var BufferTransport = class {
|
|
739
|
-
contentType = "application/octet-stream";
|
|
740
|
-
serialize(value) {
|
|
741
|
-
return value;
|
|
742
|
-
}
|
|
743
|
-
async deserialize(stream) {
|
|
744
|
-
const reader = stream.getReader();
|
|
745
|
-
const chunks = [];
|
|
746
|
-
try {
|
|
747
|
-
while (true) {
|
|
748
|
-
const { done, value } = await reader.read();
|
|
749
|
-
if (done) break;
|
|
750
|
-
chunks.push(value);
|
|
751
|
-
}
|
|
752
|
-
} finally {
|
|
753
|
-
reader.releaseLock();
|
|
754
|
-
}
|
|
755
|
-
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
756
|
-
const buffer = new Uint8Array(totalLength);
|
|
757
|
-
let offset = 0;
|
|
758
|
-
for (const chunk of chunks) {
|
|
759
|
-
buffer.set(chunk, offset);
|
|
760
|
-
offset += chunk.length;
|
|
761
|
-
}
|
|
762
|
-
return Buffer.from(buffer);
|
|
763
|
-
}
|
|
764
|
-
};
|
|
765
|
-
var StreamTransport = class {
|
|
766
|
-
contentType = "application/octet-stream";
|
|
767
|
-
serialize(value) {
|
|
768
|
-
return value;
|
|
769
|
-
}
|
|
770
|
-
async deserialize(stream) {
|
|
771
|
-
return stream;
|
|
772
|
-
}
|
|
773
|
-
async finalize(payload) {
|
|
774
|
-
const reader = payload.getReader();
|
|
775
|
-
try {
|
|
776
|
-
while (true) {
|
|
777
|
-
const { done } = await reader.read();
|
|
778
|
-
if (done) break;
|
|
779
|
-
}
|
|
780
|
-
} finally {
|
|
781
|
-
reader.releaseLock();
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
};
|
|
785
|
-
|
|
786
618
|
// src/consumer-group.ts
|
|
787
619
|
var ConsumerGroup = class {
|
|
788
620
|
client;
|
|
@@ -1014,8 +846,7 @@ var Topic = class {
|
|
|
1014
846
|
queueName: this.topicName,
|
|
1015
847
|
payload,
|
|
1016
848
|
idempotencyKey: options?.idempotencyKey,
|
|
1017
|
-
retentionSeconds: options?.retentionSeconds
|
|
1018
|
-
callback: options?.callback
|
|
849
|
+
retentionSeconds: options?.retentionSeconds
|
|
1019
850
|
},
|
|
1020
851
|
this.transport
|
|
1021
852
|
);
|
|
@@ -1054,10 +885,6 @@ var Topic = class {
|
|
|
1054
885
|
};
|
|
1055
886
|
|
|
1056
887
|
// src/factory.ts
|
|
1057
|
-
function createTopic(topicName, transport) {
|
|
1058
|
-
const client = QueueClient._getDefaultInstance();
|
|
1059
|
-
return new Topic(client, topicName, transport);
|
|
1060
|
-
}
|
|
1061
888
|
async function send(topicName, payload, options) {
|
|
1062
889
|
const transport = options?.transport || new JsonTransport();
|
|
1063
890
|
const client = QueueClient._getDefaultInstance();
|
|
@@ -1066,8 +893,7 @@ async function send(topicName, payload, options) {
|
|
|
1066
893
|
queueName: topicName,
|
|
1067
894
|
payload,
|
|
1068
895
|
idempotencyKey: options?.idempotencyKey,
|
|
1069
|
-
retentionSeconds: options?.retentionSeconds
|
|
1070
|
-
callback: options?.callback
|
|
896
|
+
retentionSeconds: options?.retentionSeconds
|
|
1071
897
|
},
|
|
1072
898
|
transport
|
|
1073
899
|
);
|
|
@@ -1075,7 +901,8 @@ async function send(topicName, payload, options) {
|
|
|
1075
901
|
}
|
|
1076
902
|
async function receive(topicName, consumerGroup, handler, options) {
|
|
1077
903
|
const transport = options?.transport || new JsonTransport();
|
|
1078
|
-
const
|
|
904
|
+
const client = QueueClient._getDefaultInstance();
|
|
905
|
+
const topic = new Topic(client, topicName, transport);
|
|
1079
906
|
const { messageId, skipPayload, ...consumerGroupOptions } = options || {};
|
|
1080
907
|
const consumer = topic.consumerGroup(consumerGroup, consumerGroupOptions);
|
|
1081
908
|
if (messageId) {
|
|
@@ -1094,23 +921,22 @@ async function receive(topicName, consumerGroup, handler, options) {
|
|
|
1094
921
|
|
|
1095
922
|
// src/callback.ts
|
|
1096
923
|
function parseCallbackRequest(request) {
|
|
1097
|
-
const
|
|
1098
|
-
const
|
|
1099
|
-
const
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
`Missing required queue callback headers: ${missingHeaders.join(", ")}`
|
|
924
|
+
const queueName = request.headers.get("Vqs-Queue-Name");
|
|
925
|
+
const consumerGroup = request.headers.get("Vqs-Consumer-Group");
|
|
926
|
+
const messageId = request.headers.get("Vqs-Message-Id");
|
|
927
|
+
if (!queueName || !consumerGroup || !messageId) {
|
|
928
|
+
const missingHeaders = [];
|
|
929
|
+
if (!queueName) missingHeaders.push("Vqs-Queue-Name");
|
|
930
|
+
if (!consumerGroup) missingHeaders.push("Vqs-Consumer-Group");
|
|
931
|
+
if (!messageId) missingHeaders.push("Vqs-Message-Id");
|
|
932
|
+
throw new Error(
|
|
933
|
+
`Missing required queue headers: ${missingHeaders.join(", ")}`
|
|
1108
934
|
);
|
|
1109
935
|
}
|
|
1110
936
|
return {
|
|
1111
|
-
messageId,
|
|
1112
937
|
queueName,
|
|
1113
|
-
consumerGroup
|
|
938
|
+
consumerGroup,
|
|
939
|
+
messageId
|
|
1114
940
|
};
|
|
1115
941
|
}
|
|
1116
942
|
function handleCallback(handlers) {
|
|
@@ -1119,41 +945,38 @@ function handleCallback(handlers) {
|
|
|
1119
945
|
const { queueName, consumerGroup, messageId } = parseCallbackRequest(request);
|
|
1120
946
|
const topicHandler = handlers[queueName];
|
|
1121
947
|
if (!topicHandler) {
|
|
1122
|
-
|
|
948
|
+
const availableTopics = Object.keys(handlers).join(", ");
|
|
949
|
+
return Response.json(
|
|
950
|
+
{
|
|
951
|
+
error: `No handler found for topic: ${queueName}`,
|
|
952
|
+
availableTopics
|
|
953
|
+
},
|
|
954
|
+
{ status: 404 }
|
|
955
|
+
);
|
|
1123
956
|
}
|
|
1124
|
-
|
|
1125
|
-
if (
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
if (!consumerGroupHandler) {
|
|
1135
|
-
const availableGroups = Object.keys(topicHandler).join(", ");
|
|
1136
|
-
throw new Error(
|
|
1137
|
-
`No handler found for consumer group "${consumerGroup}" in topic "${queueName}". Available groups: ${availableGroups}`
|
|
1138
|
-
);
|
|
1139
|
-
}
|
|
1140
|
-
actualHandler = consumerGroupHandler;
|
|
957
|
+
const consumerGroupHandler = topicHandler[consumerGroup];
|
|
958
|
+
if (!consumerGroupHandler) {
|
|
959
|
+
const availableGroups = Object.keys(topicHandler).join(", ");
|
|
960
|
+
return Response.json(
|
|
961
|
+
{
|
|
962
|
+
error: `No handler found for consumer group "${consumerGroup}" in topic "${queueName}".`,
|
|
963
|
+
availableGroups
|
|
964
|
+
},
|
|
965
|
+
{ status: 404 }
|
|
966
|
+
);
|
|
1141
967
|
}
|
|
1142
968
|
const client = new QueueClient();
|
|
1143
969
|
const topic = new Topic(client, queueName);
|
|
1144
970
|
const cg = topic.consumerGroup(consumerGroup);
|
|
1145
|
-
await cg.consume(
|
|
971
|
+
await cg.consume(consumerGroupHandler, { messageId });
|
|
1146
972
|
return Response.json({ status: "success" });
|
|
1147
973
|
} catch (error) {
|
|
1148
|
-
console.error("
|
|
1149
|
-
if (error instanceof
|
|
1150
|
-
return Response.json(
|
|
1151
|
-
{ error: "Invalid callback request" },
|
|
1152
|
-
{ status: 400 }
|
|
1153
|
-
);
|
|
974
|
+
console.error("Queue callback error:", error);
|
|
975
|
+
if (error instanceof Error && error.message.includes("Missing required queue headers")) {
|
|
976
|
+
return Response.json({ error: error.message }, { status: 400 });
|
|
1154
977
|
}
|
|
1155
978
|
return Response.json(
|
|
1156
|
-
{ error: "Failed to process
|
|
979
|
+
{ error: "Failed to process queue message" },
|
|
1157
980
|
{ status: 500 }
|
|
1158
981
|
);
|
|
1159
982
|
}
|
|
@@ -1162,26 +985,18 @@ function handleCallback(handlers) {
|
|
|
1162
985
|
export {
|
|
1163
986
|
BadRequestError,
|
|
1164
987
|
BufferTransport,
|
|
1165
|
-
ConsumerGroup,
|
|
1166
|
-
FailedDependencyError,
|
|
1167
|
-
FifoOrderingViolationError,
|
|
1168
988
|
ForbiddenError,
|
|
1169
989
|
InternalServerError,
|
|
1170
|
-
InvalidCallbackError,
|
|
1171
990
|
InvalidLimitError,
|
|
1172
991
|
JsonTransport,
|
|
1173
992
|
MessageCorruptedError,
|
|
1174
993
|
MessageLockedError,
|
|
1175
994
|
MessageNotAvailableError,
|
|
1176
995
|
MessageNotFoundError,
|
|
1177
|
-
QueueClient,
|
|
1178
996
|
QueueEmptyError,
|
|
1179
997
|
StreamTransport,
|
|
1180
|
-
Topic,
|
|
1181
998
|
UnauthorizedError,
|
|
1182
|
-
createTopic,
|
|
1183
999
|
handleCallback,
|
|
1184
|
-
parseCallbackRequest,
|
|
1185
1000
|
receive,
|
|
1186
1001
|
send
|
|
1187
1002
|
};
|