@vercel/queue 0.0.0-alpha.34 → 0.0.0-alpha.36
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 +284 -34
- package/dist/index.d.mts +208 -54
- package/dist/index.d.ts +208 -54
- package/dist/index.js +173 -38
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +173 -38
- package/dist/index.mjs.map +1 -1
- package/dist/nextjs-pages.d.mts +1 -1
- package/dist/nextjs-pages.d.ts +1 -1
- package/dist/nextjs-pages.js +145 -32
- package/dist/nextjs-pages.js.map +1 -1
- package/dist/nextjs-pages.mjs +145 -32
- package/dist/nextjs-pages.mjs.map +1 -1
- package/dist/types-C7IKe67P.d.mts +509 -0
- package/dist/types-C7IKe67P.d.ts +509 -0
- package/package.json +1 -1
- package/dist/types-BHtRP_i_.d.mts +0 -411
- package/dist/types-BHtRP_i_.d.ts +0 -411
package/dist/index.js
CHANGED
|
@@ -77,6 +77,12 @@ var JsonTransport = class {
|
|
|
77
77
|
contentType = "application/json";
|
|
78
78
|
replacer;
|
|
79
79
|
reviver;
|
|
80
|
+
/**
|
|
81
|
+
* Create a new JsonTransport.
|
|
82
|
+
* @param options - Optional JSON serialization options
|
|
83
|
+
* @param options.replacer - Custom replacer for JSON.stringify
|
|
84
|
+
* @param options.reviver - Custom reviver for JSON.parse
|
|
85
|
+
*/
|
|
80
86
|
constructor(options = {}) {
|
|
81
87
|
this.replacer = options.replacer;
|
|
82
88
|
this.reviver = options.reviver;
|
|
@@ -106,6 +112,10 @@ var StreamTransport = class {
|
|
|
106
112
|
async deserialize(stream) {
|
|
107
113
|
return stream;
|
|
108
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Consume any remaining stream data to prevent resource leaks.
|
|
117
|
+
* Called automatically by ConsumerGroup; manual call required for direct client usage.
|
|
118
|
+
*/
|
|
109
119
|
async finalize(payload) {
|
|
110
120
|
const reader = payload.getReader();
|
|
111
121
|
try {
|
|
@@ -156,6 +166,7 @@ var QueueEmptyError = class extends Error {
|
|
|
156
166
|
}
|
|
157
167
|
};
|
|
158
168
|
var MessageLockedError = class extends Error {
|
|
169
|
+
/** Suggested retry delay in seconds, if provided by the server. */
|
|
159
170
|
retryAfter;
|
|
160
171
|
constructor(messageId, retryAfter) {
|
|
161
172
|
const retryMessage = retryAfter ? ` Retry after ${retryAfter} seconds.` : " Try again later.";
|
|
@@ -201,7 +212,9 @@ var MessageAlreadyProcessedError = class extends Error {
|
|
|
201
212
|
}
|
|
202
213
|
};
|
|
203
214
|
var ConcurrencyLimitError = class extends Error {
|
|
215
|
+
/** Current number of in-flight messages for this consumer group. */
|
|
204
216
|
currentInflight;
|
|
217
|
+
/** Maximum allowed concurrent messages (as configured). */
|
|
205
218
|
maxConcurrency;
|
|
206
219
|
constructor(message = "Concurrency limit exceeded", currentInflight, maxConcurrency) {
|
|
207
220
|
super(message);
|
|
@@ -588,19 +601,55 @@ var QueueClient = class {
|
|
|
588
601
|
}
|
|
589
602
|
return response;
|
|
590
603
|
}
|
|
604
|
+
/**
|
|
605
|
+
* Send a message to a topic.
|
|
606
|
+
*
|
|
607
|
+
* @param options - Message options including queue name, payload, and optional settings
|
|
608
|
+
* @param options.queueName - Topic name (pattern: `[A-Za-z0-9_-]+`)
|
|
609
|
+
* @param options.payload - Message payload
|
|
610
|
+
* @param options.idempotencyKey - Optional deduplication key (dedup window: min(retention, 24h))
|
|
611
|
+
* @param options.retentionSeconds - Message TTL (default: 86400, min: 60, max: 86400)
|
|
612
|
+
* @param options.delaySeconds - Delivery delay (default: 0, max: retentionSeconds)
|
|
613
|
+
* @param transport - Serializer for the payload
|
|
614
|
+
* @returns Promise with the generated messageId
|
|
615
|
+
* @throws {DuplicateMessageError} When idempotency key was already used
|
|
616
|
+
* @throws {ConsumerDiscoveryError} When consumer discovery fails
|
|
617
|
+
* @throws {ConsumerRegistryNotConfiguredError} When registry not configured
|
|
618
|
+
* @throws {BadRequestError} When parameters are invalid
|
|
619
|
+
* @throws {UnauthorizedError} When authentication fails
|
|
620
|
+
* @throws {ForbiddenError} When access is denied
|
|
621
|
+
* @throws {InternalServerError} When server encounters an error
|
|
622
|
+
*/
|
|
591
623
|
async sendMessage(options, transport) {
|
|
592
624
|
const {
|
|
593
625
|
queueName,
|
|
594
626
|
payload,
|
|
595
627
|
idempotencyKey,
|
|
596
628
|
retentionSeconds,
|
|
597
|
-
delaySeconds
|
|
629
|
+
delaySeconds,
|
|
630
|
+
headers: optionHeaders
|
|
598
631
|
} = options;
|
|
599
|
-
const headers = new Headers(
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
632
|
+
const headers = new Headers();
|
|
633
|
+
if (this.customHeaders) {
|
|
634
|
+
for (const [name, value] of Object.entries(this.customHeaders)) {
|
|
635
|
+
headers.append(name, value);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
if (optionHeaders) {
|
|
639
|
+
const protectedHeaderNames = /* @__PURE__ */ new Set(["authorization", "content-type"]);
|
|
640
|
+
const isProtectedHeader = (name) => {
|
|
641
|
+
const lower = name.toLowerCase();
|
|
642
|
+
if (protectedHeaderNames.has(lower)) return true;
|
|
643
|
+
return lower.startsWith("vqs-");
|
|
644
|
+
};
|
|
645
|
+
for (const [name, value] of Object.entries(optionHeaders)) {
|
|
646
|
+
if (!isProtectedHeader(name) && value !== void 0) {
|
|
647
|
+
headers.append(name, value);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
headers.set("Authorization", `Bearer ${await this.getToken()}`);
|
|
652
|
+
headers.set("Content-Type", transport.contentType);
|
|
604
653
|
const deploymentId = this.getSendDeploymentId();
|
|
605
654
|
if (deploymentId) {
|
|
606
655
|
headers.set("Vqs-Deployment-Id", deploymentId);
|
|
@@ -650,6 +699,25 @@ var QueueClient = class {
|
|
|
650
699
|
const responseData = await response.json();
|
|
651
700
|
return responseData;
|
|
652
701
|
}
|
|
702
|
+
/**
|
|
703
|
+
* Receive messages from a topic as an async generator.
|
|
704
|
+
*
|
|
705
|
+
* @param options - Receive options
|
|
706
|
+
* @param options.queueName - Topic name (pattern: `[A-Za-z0-9_-]+`)
|
|
707
|
+
* @param options.consumerGroup - Consumer group name (pattern: `[A-Za-z0-9_-]+`)
|
|
708
|
+
* @param options.visibilityTimeoutSeconds - Lock duration (default: 30, min: 0, max: 3600)
|
|
709
|
+
* @param options.limit - Max messages to retrieve (default: 1, min: 1, max: 10)
|
|
710
|
+
* @param options.maxConcurrency - Max in-flight messages (default: unlimited, min: 1)
|
|
711
|
+
* @param transport - Deserializer for message payloads
|
|
712
|
+
* @yields Message objects with payload, messageId, receiptHandle, etc.
|
|
713
|
+
* @throws {QueueEmptyError} When no messages available
|
|
714
|
+
* @throws {InvalidLimitError} When limit is outside 1-10 range
|
|
715
|
+
* @throws {ConcurrencyLimitError} When maxConcurrency exceeded
|
|
716
|
+
* @throws {BadRequestError} When parameters are invalid
|
|
717
|
+
* @throws {UnauthorizedError} When authentication fails
|
|
718
|
+
* @throws {ForbiddenError} When access is denied
|
|
719
|
+
* @throws {InternalServerError} When server encounters an error
|
|
720
|
+
*/
|
|
653
721
|
async *receiveMessages(options, transport) {
|
|
654
722
|
const {
|
|
655
723
|
queueName,
|
|
@@ -735,6 +803,26 @@ var QueueClient = class {
|
|
|
735
803
|
}
|
|
736
804
|
}
|
|
737
805
|
}
|
|
806
|
+
/**
|
|
807
|
+
* Receive a specific message by its ID.
|
|
808
|
+
*
|
|
809
|
+
* @param options - Receive options
|
|
810
|
+
* @param options.queueName - Topic name (pattern: `[A-Za-z0-9_-]+`)
|
|
811
|
+
* @param options.consumerGroup - Consumer group name (pattern: `[A-Za-z0-9_-]+`)
|
|
812
|
+
* @param options.messageId - Message ID to retrieve
|
|
813
|
+
* @param options.visibilityTimeoutSeconds - Lock duration (default: 30, min: 0, max: 3600)
|
|
814
|
+
* @param options.maxConcurrency - Max in-flight messages (default: unlimited, min: 1)
|
|
815
|
+
* @param transport - Deserializer for the message payload
|
|
816
|
+
* @returns Promise with the message
|
|
817
|
+
* @throws {MessageNotFoundError} When message doesn't exist
|
|
818
|
+
* @throws {MessageNotAvailableError} When message is in wrong state or was a duplicate
|
|
819
|
+
* @throws {MessageAlreadyProcessedError} When message was already processed
|
|
820
|
+
* @throws {ConcurrencyLimitError} When maxConcurrency exceeded
|
|
821
|
+
* @throws {BadRequestError} When parameters are invalid
|
|
822
|
+
* @throws {UnauthorizedError} When authentication fails
|
|
823
|
+
* @throws {ForbiddenError} When access is denied
|
|
824
|
+
* @throws {InternalServerError} When server encounters an error
|
|
825
|
+
*/
|
|
738
826
|
async receiveMessageById(options, transport) {
|
|
739
827
|
const {
|
|
740
828
|
queueName,
|
|
@@ -829,6 +917,21 @@ var QueueClient = class {
|
|
|
829
917
|
}
|
|
830
918
|
throw new MessageNotFoundError(messageId);
|
|
831
919
|
}
|
|
920
|
+
/**
|
|
921
|
+
* Delete (acknowledge) a message after successful processing.
|
|
922
|
+
*
|
|
923
|
+
* @param options - Delete options
|
|
924
|
+
* @param options.queueName - Topic name
|
|
925
|
+
* @param options.consumerGroup - Consumer group name
|
|
926
|
+
* @param options.receiptHandle - Receipt handle from the received message (must use same deployment ID as receive)
|
|
927
|
+
* @returns Promise indicating deletion success
|
|
928
|
+
* @throws {MessageNotFoundError} When receipt handle not found
|
|
929
|
+
* @throws {MessageNotAvailableError} When receipt handle invalid or message already processed
|
|
930
|
+
* @throws {BadRequestError} When parameters are invalid
|
|
931
|
+
* @throws {UnauthorizedError} When authentication fails
|
|
932
|
+
* @throws {ForbiddenError} When access is denied
|
|
933
|
+
* @throws {InternalServerError} When server encounters an error
|
|
934
|
+
*/
|
|
832
935
|
async deleteMessage(options) {
|
|
833
936
|
const { queueName, consumerGroup, receiptHandle } = options;
|
|
834
937
|
const headers = new Headers({
|
|
@@ -873,6 +976,23 @@ var QueueClient = class {
|
|
|
873
976
|
}
|
|
874
977
|
return { deleted: true };
|
|
875
978
|
}
|
|
979
|
+
/**
|
|
980
|
+
* Extend or change the visibility timeout of a message.
|
|
981
|
+
* Used to prevent message redelivery while still processing.
|
|
982
|
+
*
|
|
983
|
+
* @param options - Visibility options
|
|
984
|
+
* @param options.queueName - Topic name
|
|
985
|
+
* @param options.consumerGroup - Consumer group name
|
|
986
|
+
* @param options.receiptHandle - Receipt handle from the received message (must use same deployment ID as receive)
|
|
987
|
+
* @param options.visibilityTimeoutSeconds - New timeout (min: 0, max: 3600, cannot exceed message expiration)
|
|
988
|
+
* @returns Promise indicating success
|
|
989
|
+
* @throws {MessageNotFoundError} When receipt handle not found
|
|
990
|
+
* @throws {MessageNotAvailableError} When receipt handle invalid or message already processed
|
|
991
|
+
* @throws {BadRequestError} When parameters are invalid
|
|
992
|
+
* @throws {UnauthorizedError} When authentication fails
|
|
993
|
+
* @throws {ForbiddenError} When access is denied
|
|
994
|
+
* @throws {InternalServerError} When server encounters an error
|
|
995
|
+
*/
|
|
876
996
|
async changeVisibility(options) {
|
|
877
997
|
const {
|
|
878
998
|
queueName,
|
|
@@ -995,36 +1115,26 @@ var ConsumerGroup = class {
|
|
|
995
1115
|
refreshInterval;
|
|
996
1116
|
transport;
|
|
997
1117
|
/**
|
|
998
|
-
* Create a new ConsumerGroup instance
|
|
999
|
-
*
|
|
1000
|
-
* @param
|
|
1001
|
-
* @param
|
|
1002
|
-
* @param
|
|
1118
|
+
* Create a new ConsumerGroup instance.
|
|
1119
|
+
*
|
|
1120
|
+
* @param client - QueueClient instance to use for API calls
|
|
1121
|
+
* @param topicName - Name of the topic to consume from (pattern: `[A-Za-z0-9_-]+`)
|
|
1122
|
+
* @param consumerGroupName - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
|
|
1123
|
+
* @param options - Optional configuration
|
|
1124
|
+
* @param options.transport - Payload serializer (default: JsonTransport)
|
|
1125
|
+
* @param options.visibilityTimeoutSeconds - Message lock duration (default: 30, max: 3600)
|
|
1126
|
+
* @param options.visibilityRefreshInterval - Lock refresh interval in seconds (default: visibilityTimeout / 3)
|
|
1003
1127
|
*/
|
|
1004
1128
|
constructor(client, topicName, consumerGroupName, options = {}) {
|
|
1005
1129
|
this.client = client;
|
|
1006
1130
|
this.topicName = topicName;
|
|
1007
1131
|
this.consumerGroupName = consumerGroupName;
|
|
1008
|
-
this.visibilityTimeout = options.visibilityTimeoutSeconds
|
|
1009
|
-
this.refreshInterval = options.
|
|
1132
|
+
this.visibilityTimeout = options.visibilityTimeoutSeconds ?? 30;
|
|
1133
|
+
this.refreshInterval = options.visibilityRefreshInterval ?? Math.floor(this.visibilityTimeout / 3);
|
|
1010
1134
|
this.transport = options.transport || new JsonTransport();
|
|
1011
1135
|
}
|
|
1012
1136
|
/**
|
|
1013
1137
|
* Starts a background loop that periodically extends the visibility timeout for a message.
|
|
1014
|
-
* This prevents the message from becoming visible to other consumers while it's being processed.
|
|
1015
|
-
*
|
|
1016
|
-
* The extension loop runs every `refreshInterval` seconds and updates the message's
|
|
1017
|
-
* visibility timeout to `visibilityTimeout` seconds from the current time.
|
|
1018
|
-
*
|
|
1019
|
-
* @param receiptHandle - The receipt handle that proves ownership of the message
|
|
1020
|
-
* @returns A function that when called will stop the extension loop
|
|
1021
|
-
*
|
|
1022
|
-
* @remarks
|
|
1023
|
-
* - The first extension attempt occurs after `refreshInterval` seconds, not immediately
|
|
1024
|
-
* - If an extension fails, the loop terminates with an error logged to console
|
|
1025
|
-
* - The returned stop function is idempotent - calling it multiple times is safe
|
|
1026
|
-
* - By default, the stop function returns immediately without waiting for in-flight
|
|
1027
|
-
* - Pass `true` to the stop function to wait for any in-flight extension to complete
|
|
1028
1138
|
*/
|
|
1029
1139
|
startVisibilityExtension(receiptHandle) {
|
|
1030
1140
|
let isRunning = true;
|
|
@@ -1186,7 +1296,8 @@ var Topic = class {
|
|
|
1186
1296
|
payload,
|
|
1187
1297
|
idempotencyKey: options?.idempotencyKey,
|
|
1188
1298
|
retentionSeconds: options?.retentionSeconds,
|
|
1189
|
-
delaySeconds: options?.delaySeconds
|
|
1299
|
+
delaySeconds: options?.delaySeconds,
|
|
1300
|
+
headers: options?.headers
|
|
1190
1301
|
},
|
|
1191
1302
|
this.transport
|
|
1192
1303
|
);
|
|
@@ -1296,7 +1407,7 @@ async function parseCallback(request) {
|
|
|
1296
1407
|
messageId
|
|
1297
1408
|
};
|
|
1298
1409
|
}
|
|
1299
|
-
function createCallbackHandler(handlers, client) {
|
|
1410
|
+
function createCallbackHandler(handlers, client, visibilityTimeoutSeconds) {
|
|
1300
1411
|
for (const topicPattern in handlers) {
|
|
1301
1412
|
if (topicPattern.includes("*")) {
|
|
1302
1413
|
if (!validateWildcardPattern(topicPattern)) {
|
|
@@ -1332,7 +1443,10 @@ function createCallbackHandler(handlers, client) {
|
|
|
1332
1443
|
);
|
|
1333
1444
|
}
|
|
1334
1445
|
const topic = new Topic(client, queueName);
|
|
1335
|
-
const cg = topic.consumerGroup(
|
|
1446
|
+
const cg = topic.consumerGroup(
|
|
1447
|
+
consumerGroup,
|
|
1448
|
+
visibilityTimeoutSeconds !== void 0 ? { visibilityTimeoutSeconds } : void 0
|
|
1449
|
+
);
|
|
1336
1450
|
await cg.consume(consumerGroupHandler, { messageId });
|
|
1337
1451
|
return Response.json({ status: "success" });
|
|
1338
1452
|
} catch (error) {
|
|
@@ -1348,8 +1462,12 @@ function createCallbackHandler(handlers, client) {
|
|
|
1348
1462
|
};
|
|
1349
1463
|
return routeHandler;
|
|
1350
1464
|
}
|
|
1351
|
-
function handleCallback(handlers,
|
|
1352
|
-
return createCallbackHandler(
|
|
1465
|
+
function handleCallback(handlers, options) {
|
|
1466
|
+
return createCallbackHandler(
|
|
1467
|
+
handlers,
|
|
1468
|
+
options?.client || new QueueClient(),
|
|
1469
|
+
options?.visibilityTimeoutSeconds
|
|
1470
|
+
);
|
|
1353
1471
|
}
|
|
1354
1472
|
|
|
1355
1473
|
// src/factory.ts
|
|
@@ -1362,7 +1480,8 @@ async function send(topicName, payload, options) {
|
|
|
1362
1480
|
payload,
|
|
1363
1481
|
idempotencyKey: options?.idempotencyKey,
|
|
1364
1482
|
retentionSeconds: options?.retentionSeconds,
|
|
1365
|
-
delaySeconds: options?.delaySeconds
|
|
1483
|
+
delaySeconds: options?.delaySeconds,
|
|
1484
|
+
headers: options?.headers
|
|
1366
1485
|
},
|
|
1367
1486
|
transport
|
|
1368
1487
|
);
|
|
@@ -1412,23 +1531,39 @@ var Client = class {
|
|
|
1412
1531
|
});
|
|
1413
1532
|
}
|
|
1414
1533
|
/**
|
|
1415
|
-
* Create a callback handler for processing queue messages
|
|
1416
|
-
* Returns a Next.js route handler function that routes messages to appropriate handlers
|
|
1417
|
-
*
|
|
1534
|
+
* Create a callback handler for processing queue messages.
|
|
1535
|
+
* Returns a Next.js route handler function that routes messages to appropriate handlers.
|
|
1536
|
+
*
|
|
1537
|
+
* @param handlers - Object with topic-specific handlers organized by consumer groups
|
|
1538
|
+
* @param options - Optional configuration
|
|
1539
|
+
* @param options.visibilityTimeoutSeconds - Message lock duration (default: 30, max: 3600)
|
|
1418
1540
|
* @returns A Next.js route handler function
|
|
1419
1541
|
*
|
|
1420
1542
|
* @example
|
|
1421
1543
|
* ```typescript
|
|
1544
|
+
* // Basic usage
|
|
1422
1545
|
* export const POST = client.handleCallback({
|
|
1423
1546
|
* "user-events": {
|
|
1424
1547
|
* "welcome": (user, metadata) => console.log("Welcoming user", user),
|
|
1425
1548
|
* "analytics": (user, metadata) => console.log("Tracking user", user),
|
|
1426
1549
|
* },
|
|
1427
1550
|
* });
|
|
1551
|
+
*
|
|
1552
|
+
* // With custom visibility timeout
|
|
1553
|
+
* export const POST = client.handleCallback({
|
|
1554
|
+
* "video-processing": {
|
|
1555
|
+
* "transcode": async (video) => await transcodeVideo(video),
|
|
1556
|
+
* },
|
|
1557
|
+
* }, {
|
|
1558
|
+
* visibilityTimeoutSeconds: 300, // 5 minutes for long operations
|
|
1559
|
+
* });
|
|
1428
1560
|
* ```
|
|
1429
1561
|
*/
|
|
1430
|
-
handleCallback(handlers) {
|
|
1431
|
-
return handleCallback(handlers,
|
|
1562
|
+
handleCallback(handlers, options) {
|
|
1563
|
+
return handleCallback(handlers, {
|
|
1564
|
+
...options,
|
|
1565
|
+
client: this.client
|
|
1566
|
+
});
|
|
1432
1567
|
}
|
|
1433
1568
|
};
|
|
1434
1569
|
// Annotate the CommonJS export names for ESM import in node:
|