@vercel/queue 0.0.0-alpha.34 → 0.0.0-alpha.35

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.
@@ -26,6 +26,12 @@ var JsonTransport = class {
26
26
  contentType = "application/json";
27
27
  replacer;
28
28
  reviver;
29
+ /**
30
+ * Create a new JsonTransport.
31
+ * @param options - Optional JSON serialization options
32
+ * @param options.replacer - Custom replacer for JSON.stringify
33
+ * @param options.reviver - Custom reviver for JSON.parse
34
+ */
29
35
  constructor(options = {}) {
30
36
  this.replacer = options.replacer;
31
37
  this.reviver = options.reviver;
@@ -105,7 +111,9 @@ var MessageAlreadyProcessedError = class extends Error {
105
111
  }
106
112
  };
107
113
  var ConcurrencyLimitError = class extends Error {
114
+ /** Current number of in-flight messages for this consumer group. */
108
115
  currentInflight;
116
+ /** Maximum allowed concurrent messages (as configured). */
109
117
  maxConcurrency;
110
118
  constructor(message = "Concurrency limit exceeded", currentInflight, maxConcurrency) {
111
119
  super(message);
@@ -492,6 +500,25 @@ var QueueClient = class {
492
500
  }
493
501
  return response;
494
502
  }
503
+ /**
504
+ * Send a message to a topic.
505
+ *
506
+ * @param options - Message options including queue name, payload, and optional settings
507
+ * @param options.queueName - Topic name (pattern: `[A-Za-z0-9_-]+`)
508
+ * @param options.payload - Message payload
509
+ * @param options.idempotencyKey - Optional deduplication key (dedup window: min(retention, 24h))
510
+ * @param options.retentionSeconds - Message TTL (default: 86400, min: 60, max: 86400)
511
+ * @param options.delaySeconds - Delivery delay (default: 0, max: retentionSeconds)
512
+ * @param transport - Serializer for the payload
513
+ * @returns Promise with the generated messageId
514
+ * @throws {DuplicateMessageError} When idempotency key was already used
515
+ * @throws {ConsumerDiscoveryError} When consumer discovery fails
516
+ * @throws {ConsumerRegistryNotConfiguredError} When registry not configured
517
+ * @throws {BadRequestError} When parameters are invalid
518
+ * @throws {UnauthorizedError} When authentication fails
519
+ * @throws {ForbiddenError} When access is denied
520
+ * @throws {InternalServerError} When server encounters an error
521
+ */
495
522
  async sendMessage(options, transport) {
496
523
  const {
497
524
  queueName,
@@ -554,6 +581,25 @@ var QueueClient = class {
554
581
  const responseData = await response.json();
555
582
  return responseData;
556
583
  }
584
+ /**
585
+ * Receive messages from a topic as an async generator.
586
+ *
587
+ * @param options - Receive options
588
+ * @param options.queueName - Topic name (pattern: `[A-Za-z0-9_-]+`)
589
+ * @param options.consumerGroup - Consumer group name (pattern: `[A-Za-z0-9_-]+`)
590
+ * @param options.visibilityTimeoutSeconds - Lock duration (default: 30, min: 0, max: 3600)
591
+ * @param options.limit - Max messages to retrieve (default: 1, min: 1, max: 10)
592
+ * @param options.maxConcurrency - Max in-flight messages (default: unlimited, min: 1)
593
+ * @param transport - Deserializer for message payloads
594
+ * @yields Message objects with payload, messageId, receiptHandle, etc.
595
+ * @throws {QueueEmptyError} When no messages available
596
+ * @throws {InvalidLimitError} When limit is outside 1-10 range
597
+ * @throws {ConcurrencyLimitError} When maxConcurrency exceeded
598
+ * @throws {BadRequestError} When parameters are invalid
599
+ * @throws {UnauthorizedError} When authentication fails
600
+ * @throws {ForbiddenError} When access is denied
601
+ * @throws {InternalServerError} When server encounters an error
602
+ */
557
603
  async *receiveMessages(options, transport) {
558
604
  const {
559
605
  queueName,
@@ -639,6 +685,26 @@ var QueueClient = class {
639
685
  }
640
686
  }
641
687
  }
688
+ /**
689
+ * Receive a specific message by its ID.
690
+ *
691
+ * @param options - Receive options
692
+ * @param options.queueName - Topic name (pattern: `[A-Za-z0-9_-]+`)
693
+ * @param options.consumerGroup - Consumer group name (pattern: `[A-Za-z0-9_-]+`)
694
+ * @param options.messageId - Message ID to retrieve
695
+ * @param options.visibilityTimeoutSeconds - Lock duration (default: 30, min: 0, max: 3600)
696
+ * @param options.maxConcurrency - Max in-flight messages (default: unlimited, min: 1)
697
+ * @param transport - Deserializer for the message payload
698
+ * @returns Promise with the message
699
+ * @throws {MessageNotFoundError} When message doesn't exist
700
+ * @throws {MessageNotAvailableError} When message is in wrong state or was a duplicate
701
+ * @throws {MessageAlreadyProcessedError} When message was already processed
702
+ * @throws {ConcurrencyLimitError} When maxConcurrency exceeded
703
+ * @throws {BadRequestError} When parameters are invalid
704
+ * @throws {UnauthorizedError} When authentication fails
705
+ * @throws {ForbiddenError} When access is denied
706
+ * @throws {InternalServerError} When server encounters an error
707
+ */
642
708
  async receiveMessageById(options, transport) {
643
709
  const {
644
710
  queueName,
@@ -733,6 +799,21 @@ var QueueClient = class {
733
799
  }
734
800
  throw new MessageNotFoundError(messageId);
735
801
  }
802
+ /**
803
+ * Delete (acknowledge) a message after successful processing.
804
+ *
805
+ * @param options - Delete options
806
+ * @param options.queueName - Topic name
807
+ * @param options.consumerGroup - Consumer group name
808
+ * @param options.receiptHandle - Receipt handle from the received message (must use same deployment ID as receive)
809
+ * @returns Promise indicating deletion success
810
+ * @throws {MessageNotFoundError} When receipt handle not found
811
+ * @throws {MessageNotAvailableError} When receipt handle invalid or message already processed
812
+ * @throws {BadRequestError} When parameters are invalid
813
+ * @throws {UnauthorizedError} When authentication fails
814
+ * @throws {ForbiddenError} When access is denied
815
+ * @throws {InternalServerError} When server encounters an error
816
+ */
736
817
  async deleteMessage(options) {
737
818
  const { queueName, consumerGroup, receiptHandle } = options;
738
819
  const headers = new Headers({
@@ -777,6 +858,23 @@ var QueueClient = class {
777
858
  }
778
859
  return { deleted: true };
779
860
  }
861
+ /**
862
+ * Extend or change the visibility timeout of a message.
863
+ * Used to prevent message redelivery while still processing.
864
+ *
865
+ * @param options - Visibility options
866
+ * @param options.queueName - Topic name
867
+ * @param options.consumerGroup - Consumer group name
868
+ * @param options.receiptHandle - Receipt handle from the received message (must use same deployment ID as receive)
869
+ * @param options.visibilityTimeoutSeconds - New timeout (min: 0, max: 3600, cannot exceed message expiration)
870
+ * @returns Promise indicating success
871
+ * @throws {MessageNotFoundError} When receipt handle not found
872
+ * @throws {MessageNotAvailableError} When receipt handle invalid or message already processed
873
+ * @throws {BadRequestError} When parameters are invalid
874
+ * @throws {UnauthorizedError} When authentication fails
875
+ * @throws {ForbiddenError} When access is denied
876
+ * @throws {InternalServerError} When server encounters an error
877
+ */
780
878
  async changeVisibility(options) {
781
879
  const {
782
880
  queueName,
@@ -899,36 +997,26 @@ var ConsumerGroup = class {
899
997
  refreshInterval;
900
998
  transport;
901
999
  /**
902
- * Create a new ConsumerGroup instance
903
- * @param client QueueClient instance to use for API calls
904
- * @param topicName Name of the topic to consume from
905
- * @param consumerGroupName Name of the consumer group
906
- * @param options Optional configuration
1000
+ * Create a new ConsumerGroup instance.
1001
+ *
1002
+ * @param client - QueueClient instance to use for API calls
1003
+ * @param topicName - Name of the topic to consume from (pattern: `[A-Za-z0-9_-]+`)
1004
+ * @param consumerGroupName - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
1005
+ * @param options - Optional configuration
1006
+ * @param options.transport - Payload serializer (default: JsonTransport)
1007
+ * @param options.visibilityTimeoutSeconds - Message lock duration (default: 30, max: 3600)
1008
+ * @param options.visibilityRefreshInterval - Lock refresh interval in seconds (default: visibilityTimeout / 3)
907
1009
  */
908
1010
  constructor(client, topicName, consumerGroupName, options = {}) {
909
1011
  this.client = client;
910
1012
  this.topicName = topicName;
911
1013
  this.consumerGroupName = consumerGroupName;
912
- this.visibilityTimeout = options.visibilityTimeoutSeconds || 30;
913
- this.refreshInterval = options.refreshInterval || 10;
1014
+ this.visibilityTimeout = options.visibilityTimeoutSeconds ?? 30;
1015
+ this.refreshInterval = options.visibilityRefreshInterval ?? Math.floor(this.visibilityTimeout / 3);
914
1016
  this.transport = options.transport || new JsonTransport();
915
1017
  }
916
1018
  /**
917
1019
  * Starts a background loop that periodically extends the visibility timeout for a message.
918
- * This prevents the message from becoming visible to other consumers while it's being processed.
919
- *
920
- * The extension loop runs every `refreshInterval` seconds and updates the message's
921
- * visibility timeout to `visibilityTimeout` seconds from the current time.
922
- *
923
- * @param receiptHandle - The receipt handle that proves ownership of the message
924
- * @returns A function that when called will stop the extension loop
925
- *
926
- * @remarks
927
- * - The first extension attempt occurs after `refreshInterval` seconds, not immediately
928
- * - If an extension fails, the loop terminates with an error logged to console
929
- * - The returned stop function is idempotent - calling it multiple times is safe
930
- * - By default, the stop function returns immediately without waiting for in-flight
931
- * - Pass `true` to the stop function to wait for any in-flight extension to complete
932
1020
  */
933
1021
  startVisibilityExtension(receiptHandle) {
934
1022
  let isRunning = true;
@@ -1200,7 +1288,7 @@ async function parseCallback(request) {
1200
1288
  messageId
1201
1289
  };
1202
1290
  }
1203
- function createCallbackHandler(handlers, client) {
1291
+ function createCallbackHandler(handlers, client, visibilityTimeoutSeconds) {
1204
1292
  for (const topicPattern in handlers) {
1205
1293
  if (topicPattern.includes("*")) {
1206
1294
  if (!validateWildcardPattern(topicPattern)) {
@@ -1236,7 +1324,10 @@ function createCallbackHandler(handlers, client) {
1236
1324
  );
1237
1325
  }
1238
1326
  const topic = new Topic(client, queueName);
1239
- const cg = topic.consumerGroup(consumerGroup);
1327
+ const cg = topic.consumerGroup(
1328
+ consumerGroup,
1329
+ visibilityTimeoutSeconds !== void 0 ? { visibilityTimeoutSeconds } : void 0
1330
+ );
1240
1331
  await cg.consume(consumerGroupHandler, { messageId });
1241
1332
  return Response.json({ status: "success" });
1242
1333
  } catch (error) {
@@ -1252,8 +1343,12 @@ function createCallbackHandler(handlers, client) {
1252
1343
  };
1253
1344
  return routeHandler;
1254
1345
  }
1255
- function handleCallback(handlers, client) {
1256
- return createCallbackHandler(handlers, client || new QueueClient());
1346
+ function handleCallback(handlers, options) {
1347
+ return createCallbackHandler(
1348
+ handlers,
1349
+ options?.client || new QueueClient(),
1350
+ options?.visibilityTimeoutSeconds
1351
+ );
1257
1352
  }
1258
1353
 
1259
1354
  // src/nextjs-pages.ts