@vercel/queue 0.0.2 → 0.1.0
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 +78 -59
- package/dist/index.d.mts +122 -37
- package/dist/index.d.ts +122 -37
- package/dist/index.js +127 -79
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +126 -79
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -37,12 +37,11 @@ interface Transport<T = unknown> {
|
|
|
37
37
|
* @example
|
|
38
38
|
* ```typescript
|
|
39
39
|
* // Default (JsonTransport is used automatically)
|
|
40
|
-
* const queue = new QueueClient(
|
|
40
|
+
* const queue = new QueueClient();
|
|
41
41
|
* await queue.send("topic", { data: "example" });
|
|
42
42
|
*
|
|
43
43
|
* // With custom serialization
|
|
44
44
|
* const queue = new QueueClient({
|
|
45
|
-
* region: process.env.QUEUE_REGION!,
|
|
46
45
|
* transport: new JsonTransport({
|
|
47
46
|
* replacer: (key, value) => key === "password" ? undefined : value,
|
|
48
47
|
* reviver: (key, value) => key === "date" ? new Date(value) : value,
|
|
@@ -75,7 +74,7 @@ declare class JsonTransport<T = unknown> implements Transport<T> {
|
|
|
75
74
|
*
|
|
76
75
|
* @example
|
|
77
76
|
* ```typescript
|
|
78
|
-
* const queue = new QueueClient({
|
|
77
|
+
* const queue = new QueueClient({ transport: new BufferTransport() });
|
|
79
78
|
* await queue.send("binary-topic", myBuffer);
|
|
80
79
|
* ```
|
|
81
80
|
*/
|
|
@@ -95,13 +94,13 @@ declare class BufferTransport implements Transport<Buffer> {
|
|
|
95
94
|
*
|
|
96
95
|
* @example
|
|
97
96
|
* ```typescript
|
|
98
|
-
* const queue = new QueueClient({ region: "iad1", transport: new StreamTransport() });
|
|
99
|
-
*
|
|
100
97
|
* // Sending a stream
|
|
98
|
+
* const queue = new QueueClient({ transport: new StreamTransport() });
|
|
101
99
|
* await queue.send("large-file", myReadableStream);
|
|
102
100
|
*
|
|
103
101
|
* // Receiving - cleanup handled automatically
|
|
104
|
-
*
|
|
102
|
+
* const poller = new PollingQueueClient({ region: "iad1", transport: new StreamTransport() });
|
|
103
|
+
* await poller.receive("large-file", "processor", async (stream, meta) => {
|
|
105
104
|
* const reader = stream.getReader();
|
|
106
105
|
* // Process chunks...
|
|
107
106
|
* });
|
|
@@ -155,15 +154,17 @@ interface QueueClientOptions {
|
|
|
155
154
|
* Requests are sent to the regional endpoint resolved by
|
|
156
155
|
* {@link BaseUrlResolver} (default: `https://${region}.vercel-queue.com`).
|
|
157
156
|
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
157
|
+
* When omitted, the region is auto-detected from the `VERCEL_REGION`
|
|
158
|
+
* environment variable (set automatically on Vercel). If not available,
|
|
159
|
+
* defaults to `"iad1"` with a console warning.
|
|
160
160
|
*
|
|
161
161
|
* @example
|
|
162
162
|
* ```ts
|
|
163
|
-
* new QueueClient(
|
|
163
|
+
* new QueueClient() // auto-detect, falls back to "iad1"
|
|
164
|
+
* new QueueClient({ region: "iad1" }) // explicit
|
|
164
165
|
* ```
|
|
165
166
|
*/
|
|
166
|
-
region
|
|
167
|
+
region?: VercelRegion;
|
|
167
168
|
/**
|
|
168
169
|
* Custom resolver that maps a region code to a base {@link URL}.
|
|
169
170
|
*
|
|
@@ -205,6 +206,28 @@ interface QueueClientOptions {
|
|
|
205
206
|
*/
|
|
206
207
|
transport?: Transport;
|
|
207
208
|
}
|
|
209
|
+
/**
|
|
210
|
+
* Options for creating a {@link PollingQueueClient}.
|
|
211
|
+
*
|
|
212
|
+
* Identical to {@link QueueClientOptions} except `region` is **required**
|
|
213
|
+
* because messages can only be received from the region they were sent to.
|
|
214
|
+
* Using a fixed region (e.g. `"iad1"`) ensures that `send` and `receive`
|
|
215
|
+
* target the same endpoint.
|
|
216
|
+
*/
|
|
217
|
+
interface PollingQueueClientOptions extends QueueClientOptions {
|
|
218
|
+
/**
|
|
219
|
+
* Vercel region code for API routing — **required** for polling.
|
|
220
|
+
*
|
|
221
|
+
* Messages can only be received from the region they were sent to.
|
|
222
|
+
* Use a fixed region (e.g. `"iad1"`) for both sending and receiving.
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```ts
|
|
226
|
+
* new PollingQueueClient({ region: "iad1" })
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
region: VercelRegion;
|
|
230
|
+
}
|
|
208
231
|
/**
|
|
209
232
|
* Options for sending messages.
|
|
210
233
|
*/
|
|
@@ -496,14 +519,37 @@ declare class ConsumerRegistryNotConfiguredError extends Error {
|
|
|
496
519
|
constructor(message?: string);
|
|
497
520
|
}
|
|
498
521
|
|
|
522
|
+
/**
|
|
523
|
+
* Queue client for push-based (callback) workflows.
|
|
524
|
+
*
|
|
525
|
+
* Use this client when Vercel delivers messages to your route handlers.
|
|
526
|
+
* Provides {@link send}, {@link handleCallback}, and {@link handleNodeCallback}.
|
|
527
|
+
*
|
|
528
|
+
* Region is resolved automatically:
|
|
529
|
+
* 1. Explicit `region` option (highest priority)
|
|
530
|
+
* 2. `VERCEL_REGION` environment variable (set automatically on Vercel)
|
|
531
|
+
* 3. Falls back to `"iad1"` with a console warning
|
|
532
|
+
*
|
|
533
|
+
* The constructor never throws — `new QueueClient()` always works.
|
|
534
|
+
*
|
|
535
|
+
* For manual polling workflows, use {@link PollingQueueClient} instead.
|
|
536
|
+
*
|
|
537
|
+
* @example
|
|
538
|
+
* ```typescript
|
|
539
|
+
* import { QueueClient } from "@vercel/queue";
|
|
540
|
+
*
|
|
541
|
+
* const queue = new QueueClient();
|
|
542
|
+
* export const { send, handleCallback, handleNodeCallback } = queue;
|
|
543
|
+
* ```
|
|
544
|
+
*/
|
|
499
545
|
declare class QueueClient {
|
|
500
|
-
constructor(options
|
|
546
|
+
constructor(options?: QueueClientOptions);
|
|
501
547
|
/**
|
|
502
548
|
* Send a message to a topic.
|
|
503
549
|
*
|
|
504
550
|
* This is an arrow function property so it can be destructured:
|
|
505
551
|
* ```typescript
|
|
506
|
-
* const { send } = new QueueClient(
|
|
552
|
+
* const { send } = new QueueClient();
|
|
507
553
|
* await send("my-topic", payload);
|
|
508
554
|
* ```
|
|
509
555
|
*
|
|
@@ -514,28 +560,6 @@ declare class QueueClient {
|
|
|
514
560
|
* the message for deferred processing (no ID available yet)
|
|
515
561
|
*/
|
|
516
562
|
send: <T = unknown>(topicName: string, payload: T, options?: SendOptions) => Promise<SendResult>;
|
|
517
|
-
/**
|
|
518
|
-
* Receive and process messages from a topic.
|
|
519
|
-
*
|
|
520
|
-
* Each message is automatically locked, kept alive via periodic visibility
|
|
521
|
-
* extensions during processing, and acknowledged upon successful handler completion.
|
|
522
|
-
* The handler is not called when the queue is empty — check `result.ok` instead.
|
|
523
|
-
*
|
|
524
|
-
* This is an arrow function property so it can be destructured:
|
|
525
|
-
* ```typescript
|
|
526
|
-
* const { receive } = new QueueClient({ region: process.env.QUEUE_REGION! });
|
|
527
|
-
* const result = await receive("my-topic", "my-group", handler);
|
|
528
|
-
* if (!result.ok) console.log(result.reason);
|
|
529
|
-
* ```
|
|
530
|
-
*
|
|
531
|
-
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
532
|
-
* @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
|
|
533
|
-
* @param handler - Function to process each message payload and metadata.
|
|
534
|
-
* Not called when the queue is empty.
|
|
535
|
-
* @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)
|
|
536
|
-
* @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise
|
|
537
|
-
*/
|
|
538
|
-
receive: <T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options?: ReceiveOptions) => Promise<ReceiveResult>;
|
|
539
563
|
/**
|
|
540
564
|
* Create a Web API route handler for processing queue callback messages.
|
|
541
565
|
*
|
|
@@ -544,7 +568,7 @@ declare class QueueClient {
|
|
|
544
568
|
*
|
|
545
569
|
* This is an arrow function property so it can be destructured:
|
|
546
570
|
* ```typescript
|
|
547
|
-
* const { handleCallback } = new QueueClient(
|
|
571
|
+
* const { handleCallback } = new QueueClient();
|
|
548
572
|
* export const POST = handleCallback(handler);
|
|
549
573
|
* ```
|
|
550
574
|
*
|
|
@@ -568,7 +592,7 @@ declare class QueueClient {
|
|
|
568
592
|
*
|
|
569
593
|
* This is an arrow function property so it can be destructured:
|
|
570
594
|
* ```typescript
|
|
571
|
-
* const { handleNodeCallback } = new QueueClient(
|
|
595
|
+
* const { handleNodeCallback } = new QueueClient();
|
|
572
596
|
* app.post("/api/queue", handleNodeCallback(handler));
|
|
573
597
|
* ```
|
|
574
598
|
*
|
|
@@ -594,6 +618,67 @@ declare class QueueClient {
|
|
|
594
618
|
end(): void;
|
|
595
619
|
}) => Promise<void>);
|
|
596
620
|
}
|
|
621
|
+
/**
|
|
622
|
+
* Queue client for poll-based (manual receive) workflows.
|
|
623
|
+
*
|
|
624
|
+
* Use this client when you manually poll for messages with {@link receive}.
|
|
625
|
+
* Also provides {@link send} for publishing messages.
|
|
626
|
+
*
|
|
627
|
+
* Region is **required** because messages can only be received from the
|
|
628
|
+
* region they were sent to. Use a fixed region (e.g. `"iad1"`) for both
|
|
629
|
+
* sending and receiving.
|
|
630
|
+
*
|
|
631
|
+
* For push-based (callback) workflows on Vercel, use {@link QueueClient} instead.
|
|
632
|
+
*
|
|
633
|
+
* @example
|
|
634
|
+
* ```typescript
|
|
635
|
+
* import { PollingQueueClient } from "@vercel/queue";
|
|
636
|
+
*
|
|
637
|
+
* const queue = new PollingQueueClient({ region: "iad1" });
|
|
638
|
+
* export const { send, receive } = queue;
|
|
639
|
+
* ```
|
|
640
|
+
*/
|
|
641
|
+
declare class PollingQueueClient {
|
|
642
|
+
constructor(options: PollingQueueClientOptions);
|
|
643
|
+
/**
|
|
644
|
+
* Send a message to a topic.
|
|
645
|
+
*
|
|
646
|
+
* This is an arrow function property so it can be destructured:
|
|
647
|
+
* ```typescript
|
|
648
|
+
* const { send } = new PollingQueueClient({ region: "iad1" });
|
|
649
|
+
* await send("my-topic", payload);
|
|
650
|
+
* ```
|
|
651
|
+
*
|
|
652
|
+
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
653
|
+
* @param payload - The data to send (serialized via the configured transport)
|
|
654
|
+
* @param options - Optional send options (idempotencyKey, retentionSeconds, delaySeconds, headers)
|
|
655
|
+
* @returns `{ messageId }` — `messageId` is `null` when the server accepted
|
|
656
|
+
* the message for deferred processing (no ID available yet)
|
|
657
|
+
*/
|
|
658
|
+
send: <T = unknown>(topicName: string, payload: T, options?: SendOptions) => Promise<SendResult>;
|
|
659
|
+
/**
|
|
660
|
+
* Receive and process messages from a topic.
|
|
661
|
+
*
|
|
662
|
+
* Each message is automatically locked, kept alive via periodic visibility
|
|
663
|
+
* extensions during processing, and acknowledged upon successful handler completion.
|
|
664
|
+
* The handler is not called when the queue is empty — check `result.ok` instead.
|
|
665
|
+
*
|
|
666
|
+
* This is an arrow function property so it can be destructured:
|
|
667
|
+
* ```typescript
|
|
668
|
+
* const { receive } = new PollingQueueClient({ region: "iad1" });
|
|
669
|
+
* const result = await receive("my-topic", "my-group", handler);
|
|
670
|
+
* if (!result.ok) console.log(result.reason);
|
|
671
|
+
* ```
|
|
672
|
+
*
|
|
673
|
+
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
674
|
+
* @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
|
|
675
|
+
* @param handler - Function to process each message payload and metadata.
|
|
676
|
+
* Not called when the queue is empty.
|
|
677
|
+
* @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)
|
|
678
|
+
* @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise
|
|
679
|
+
*/
|
|
680
|
+
receive: <T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options?: ReceiveOptions) => Promise<ReceiveResult>;
|
|
681
|
+
}
|
|
597
682
|
|
|
598
683
|
/**
|
|
599
684
|
* Core queue callback utilities for handling incoming webhook payloads
|
|
@@ -668,4 +753,4 @@ declare function parseRawCallback(body: unknown, headers: Record<string, string
|
|
|
668
753
|
*/
|
|
669
754
|
declare function parseCallback(request: Request): Promise<ParsedCallbackRequest>;
|
|
670
755
|
|
|
671
|
-
export { BadRequestError, type BaseUrlResolver, BufferTransport, CLOUD_EVENT_TYPE_V1BETA, CLOUD_EVENT_TYPE_V2BETA, ConsumerDiscoveryError, ConsumerRegistryNotConfiguredError, DuplicateMessageError, ForbiddenError, InternalServerError, InvalidLimitError, JsonTransport, type Message, MessageAlreadyProcessedError, MessageCorruptedError, type MessageHandler, MessageLockedError, type MessageMetadata, MessageNotAvailableError, MessageNotFoundError, type ParsedCallbackRequest, type ParsedCallbackV1, type ParsedCallbackV2, QueueClient, type QueueClientOptions, QueueEmptyError, type ReceiveBatchOptions, type ReceiveByIdOptions, type ReceiveOptions, type ReceiveResult, type RetryDirective, type RetryHandler, type SendOptions, type SendResult, StreamTransport, type Transport, UnauthorizedError, type VercelRegion, parseCallback, parseRawCallback };
|
|
756
|
+
export { BadRequestError, type BaseUrlResolver, BufferTransport, CLOUD_EVENT_TYPE_V1BETA, CLOUD_EVENT_TYPE_V2BETA, ConsumerDiscoveryError, ConsumerRegistryNotConfiguredError, DuplicateMessageError, ForbiddenError, InternalServerError, InvalidLimitError, JsonTransport, type Message, MessageAlreadyProcessedError, MessageCorruptedError, type MessageHandler, MessageLockedError, type MessageMetadata, MessageNotAvailableError, MessageNotFoundError, type ParsedCallbackRequest, type ParsedCallbackV1, type ParsedCallbackV2, PollingQueueClient, type PollingQueueClientOptions, QueueClient, type QueueClientOptions, QueueEmptyError, type ReceiveBatchOptions, type ReceiveByIdOptions, type ReceiveOptions, type ReceiveResult, type RetryDirective, type RetryHandler, type SendOptions, type SendResult, StreamTransport, type Transport, UnauthorizedError, type VercelRegion, parseCallback, parseRawCallback };
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,7 @@ __export(index_exports, {
|
|
|
46
46
|
MessageLockedError: () => MessageLockedError,
|
|
47
47
|
MessageNotAvailableError: () => MessageNotAvailableError,
|
|
48
48
|
MessageNotFoundError: () => MessageNotFoundError,
|
|
49
|
+
PollingQueueClient: () => PollingQueueClient,
|
|
49
50
|
QueueClient: () => QueueClient,
|
|
50
51
|
QueueEmptyError: () => QueueEmptyError,
|
|
51
52
|
StreamTransport: () => StreamTransport,
|
|
@@ -1079,7 +1080,7 @@ var ApiClient = class _ApiClient {
|
|
|
1079
1080
|
return;
|
|
1080
1081
|
}
|
|
1081
1082
|
throw new Error(
|
|
1082
|
-
'No deployment ID available. VERCEL_DEPLOYMENT_ID is not set.\n\nThis usually means the code is running outside a Vercel deployment (e.g. during build or in a non-Vercel environment).\n\nTo fix this, create a
|
|
1083
|
+
'No deployment ID available. VERCEL_DEPLOYMENT_ID is not set.\n\nThis usually means the code is running outside a Vercel deployment (e.g. during build or in a non-Vercel environment).\n\nTo fix this, create a client with an explicit deploymentId:\n new QueueClient({ deploymentId: "dpl_xxx" })\nOr explicitly opt out of deployment pinning:\n new QueueClient({ deploymentId: null })'
|
|
1083
1084
|
);
|
|
1084
1085
|
}
|
|
1085
1086
|
getSendDeploymentId() {
|
|
@@ -1137,7 +1138,7 @@ var ApiClient = class _ApiClient {
|
|
|
1137
1138
|
}
|
|
1138
1139
|
console.debug("[VQS Debug] Request:", JSON.stringify(logData, null, 2));
|
|
1139
1140
|
}
|
|
1140
|
-
init.headers.set("User-Agent", `@vercel/queue/${"0.0
|
|
1141
|
+
init.headers.set("User-Agent", `@vercel/queue/${"0.1.0"}`);
|
|
1141
1142
|
init.headers.set("Vqs-Client-Ts", (/* @__PURE__ */ new Date()).toISOString());
|
|
1142
1143
|
const response = await fetch(url, init);
|
|
1143
1144
|
if (isDebugEnabled()) {
|
|
@@ -1473,23 +1474,37 @@ var ApiClient = class _ApiClient {
|
|
|
1473
1474
|
|
|
1474
1475
|
// src/client.ts
|
|
1475
1476
|
var apiClients = /* @__PURE__ */ new WeakMap();
|
|
1476
|
-
function
|
|
1477
|
+
function getApi(client) {
|
|
1477
1478
|
const api = apiClients.get(client);
|
|
1478
1479
|
if (!api) {
|
|
1479
|
-
throw new Error("
|
|
1480
|
+
throw new Error("Client not initialized");
|
|
1480
1481
|
}
|
|
1481
1482
|
return api;
|
|
1482
1483
|
}
|
|
1484
|
+
function getApiClient(client) {
|
|
1485
|
+
return getApi(client);
|
|
1486
|
+
}
|
|
1487
|
+
var DEFAULT_REGION = "iad1";
|
|
1488
|
+
function resolveRegion(region) {
|
|
1489
|
+
if (region) return region;
|
|
1490
|
+
const fromEnv = process.env.VERCEL_REGION;
|
|
1491
|
+
if (fromEnv) return fromEnv;
|
|
1492
|
+
console.warn(
|
|
1493
|
+
`[QueueClient] Region not detected \u2014 defaulting to "${DEFAULT_REGION}". On Vercel this is set automatically via VERCEL_REGION. To silence this warning, pass region explicitly: new QueueClient({ region: "iad1" })`
|
|
1494
|
+
);
|
|
1495
|
+
return DEFAULT_REGION;
|
|
1496
|
+
}
|
|
1483
1497
|
var QueueClient = class {
|
|
1484
|
-
constructor(options) {
|
|
1485
|
-
|
|
1498
|
+
constructor(options = {}) {
|
|
1499
|
+
const region = resolveRegion(options.region);
|
|
1500
|
+
apiClients.set(this, new ApiClient({ ...options, region }));
|
|
1486
1501
|
}
|
|
1487
1502
|
/**
|
|
1488
1503
|
* Send a message to a topic.
|
|
1489
1504
|
*
|
|
1490
1505
|
* This is an arrow function property so it can be destructured:
|
|
1491
1506
|
* ```typescript
|
|
1492
|
-
* const { send } = new QueueClient(
|
|
1507
|
+
* const { send } = new QueueClient();
|
|
1493
1508
|
* await send("my-topic", payload);
|
|
1494
1509
|
* ```
|
|
1495
1510
|
*
|
|
@@ -1500,7 +1515,7 @@ var QueueClient = class {
|
|
|
1500
1515
|
* the message for deferred processing (no ID available yet)
|
|
1501
1516
|
*/
|
|
1502
1517
|
send = async (topicName, payload, options) => {
|
|
1503
|
-
const api =
|
|
1518
|
+
const api = getApi(this);
|
|
1504
1519
|
const result = await api.sendMessage({
|
|
1505
1520
|
queueName: topicName,
|
|
1506
1521
|
payload,
|
|
@@ -1519,75 +1534,6 @@ var QueueClient = class {
|
|
|
1519
1534
|
}
|
|
1520
1535
|
return { messageId: result.messageId };
|
|
1521
1536
|
};
|
|
1522
|
-
/**
|
|
1523
|
-
* Receive and process messages from a topic.
|
|
1524
|
-
*
|
|
1525
|
-
* Each message is automatically locked, kept alive via periodic visibility
|
|
1526
|
-
* extensions during processing, and acknowledged upon successful handler completion.
|
|
1527
|
-
* The handler is not called when the queue is empty — check `result.ok` instead.
|
|
1528
|
-
*
|
|
1529
|
-
* This is an arrow function property so it can be destructured:
|
|
1530
|
-
* ```typescript
|
|
1531
|
-
* const { receive } = new QueueClient({ region: process.env.QUEUE_REGION! });
|
|
1532
|
-
* const result = await receive("my-topic", "my-group", handler);
|
|
1533
|
-
* if (!result.ok) console.log(result.reason);
|
|
1534
|
-
* ```
|
|
1535
|
-
*
|
|
1536
|
-
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
1537
|
-
* @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
|
|
1538
|
-
* @param handler - Function to process each message payload and metadata.
|
|
1539
|
-
* Not called when the queue is empty.
|
|
1540
|
-
* @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)
|
|
1541
|
-
* @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise
|
|
1542
|
-
*/
|
|
1543
|
-
receive = async (topicName, consumerGroup, handler, options) => {
|
|
1544
|
-
const api = getApiClient(this);
|
|
1545
|
-
const topic = new Topic(api, topicName);
|
|
1546
|
-
const visibilityTimeoutSeconds = options && "visibilityTimeoutSeconds" in options ? options.visibilityTimeoutSeconds : void 0;
|
|
1547
|
-
const consumer = topic.consumerGroup(
|
|
1548
|
-
consumerGroup,
|
|
1549
|
-
visibilityTimeoutSeconds !== void 0 ? { visibilityTimeoutSeconds } : {}
|
|
1550
|
-
);
|
|
1551
|
-
try {
|
|
1552
|
-
let count;
|
|
1553
|
-
const retry = options?.retry;
|
|
1554
|
-
if (options && "messageId" in options) {
|
|
1555
|
-
count = await consumer.consume(handler, {
|
|
1556
|
-
messageId: options.messageId,
|
|
1557
|
-
retry
|
|
1558
|
-
});
|
|
1559
|
-
} else {
|
|
1560
|
-
const limit = options && "limit" in options ? options.limit : void 0;
|
|
1561
|
-
count = await consumer.consume(handler, {
|
|
1562
|
-
...limit !== void 0 ? { limit } : {},
|
|
1563
|
-
retry
|
|
1564
|
-
});
|
|
1565
|
-
}
|
|
1566
|
-
if (count === 0) {
|
|
1567
|
-
return { ok: false, reason: "empty" };
|
|
1568
|
-
}
|
|
1569
|
-
return { ok: true };
|
|
1570
|
-
} catch (error) {
|
|
1571
|
-
if (options && "messageId" in options && error instanceof MessageNotFoundError) {
|
|
1572
|
-
return { ok: false, reason: "not_found", messageId: options.messageId };
|
|
1573
|
-
}
|
|
1574
|
-
if (options && "messageId" in options && error instanceof MessageNotAvailableError) {
|
|
1575
|
-
return {
|
|
1576
|
-
ok: false,
|
|
1577
|
-
reason: "not_available",
|
|
1578
|
-
messageId: options.messageId
|
|
1579
|
-
};
|
|
1580
|
-
}
|
|
1581
|
-
if (options && "messageId" in options && error instanceof MessageAlreadyProcessedError) {
|
|
1582
|
-
return {
|
|
1583
|
-
ok: false,
|
|
1584
|
-
reason: "already_processed",
|
|
1585
|
-
messageId: options.messageId
|
|
1586
|
-
};
|
|
1587
|
-
}
|
|
1588
|
-
throw error;
|
|
1589
|
-
}
|
|
1590
|
-
};
|
|
1591
1537
|
/**
|
|
1592
1538
|
* Create a Web API route handler for processing queue callback messages.
|
|
1593
1539
|
*
|
|
@@ -1596,7 +1542,7 @@ var QueueClient = class {
|
|
|
1596
1542
|
*
|
|
1597
1543
|
* This is an arrow function property so it can be destructured:
|
|
1598
1544
|
* ```typescript
|
|
1599
|
-
* const { handleCallback } = new QueueClient(
|
|
1545
|
+
* const { handleCallback } = new QueueClient();
|
|
1600
1546
|
* export const POST = handleCallback(handler);
|
|
1601
1547
|
* ```
|
|
1602
1548
|
*
|
|
@@ -1638,7 +1584,7 @@ var QueueClient = class {
|
|
|
1638
1584
|
*
|
|
1639
1585
|
* This is an arrow function property so it can be destructured:
|
|
1640
1586
|
* ```typescript
|
|
1641
|
-
* const { handleNodeCallback } = new QueueClient(
|
|
1587
|
+
* const { handleNodeCallback } = new QueueClient();
|
|
1642
1588
|
* app.post("/api/queue", handleNodeCallback(handler));
|
|
1643
1589
|
* ```
|
|
1644
1590
|
*
|
|
@@ -1674,6 +1620,107 @@ var QueueClient = class {
|
|
|
1674
1620
|
};
|
|
1675
1621
|
};
|
|
1676
1622
|
};
|
|
1623
|
+
var PollingQueueClient = class {
|
|
1624
|
+
constructor(options) {
|
|
1625
|
+
apiClients.set(this, new ApiClient(options));
|
|
1626
|
+
}
|
|
1627
|
+
/**
|
|
1628
|
+
* Send a message to a topic.
|
|
1629
|
+
*
|
|
1630
|
+
* This is an arrow function property so it can be destructured:
|
|
1631
|
+
* ```typescript
|
|
1632
|
+
* const { send } = new PollingQueueClient({ region: "iad1" });
|
|
1633
|
+
* await send("my-topic", payload);
|
|
1634
|
+
* ```
|
|
1635
|
+
*
|
|
1636
|
+
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
1637
|
+
* @param payload - The data to send (serialized via the configured transport)
|
|
1638
|
+
* @param options - Optional send options (idempotencyKey, retentionSeconds, delaySeconds, headers)
|
|
1639
|
+
* @returns `{ messageId }` — `messageId` is `null` when the server accepted
|
|
1640
|
+
* the message for deferred processing (no ID available yet)
|
|
1641
|
+
*/
|
|
1642
|
+
send = async (topicName, payload, options) => {
|
|
1643
|
+
const api = getApi(this);
|
|
1644
|
+
const result = await api.sendMessage({
|
|
1645
|
+
queueName: topicName,
|
|
1646
|
+
payload,
|
|
1647
|
+
idempotencyKey: options?.idempotencyKey,
|
|
1648
|
+
retentionSeconds: options?.retentionSeconds,
|
|
1649
|
+
delaySeconds: options?.delaySeconds,
|
|
1650
|
+
headers: options?.headers
|
|
1651
|
+
});
|
|
1652
|
+
return { messageId: result.messageId };
|
|
1653
|
+
};
|
|
1654
|
+
/**
|
|
1655
|
+
* Receive and process messages from a topic.
|
|
1656
|
+
*
|
|
1657
|
+
* Each message is automatically locked, kept alive via periodic visibility
|
|
1658
|
+
* extensions during processing, and acknowledged upon successful handler completion.
|
|
1659
|
+
* The handler is not called when the queue is empty — check `result.ok` instead.
|
|
1660
|
+
*
|
|
1661
|
+
* This is an arrow function property so it can be destructured:
|
|
1662
|
+
* ```typescript
|
|
1663
|
+
* const { receive } = new PollingQueueClient({ region: "iad1" });
|
|
1664
|
+
* const result = await receive("my-topic", "my-group", handler);
|
|
1665
|
+
* if (!result.ok) console.log(result.reason);
|
|
1666
|
+
* ```
|
|
1667
|
+
*
|
|
1668
|
+
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
1669
|
+
* @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
|
|
1670
|
+
* @param handler - Function to process each message payload and metadata.
|
|
1671
|
+
* Not called when the queue is empty.
|
|
1672
|
+
* @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)
|
|
1673
|
+
* @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise
|
|
1674
|
+
*/
|
|
1675
|
+
receive = async (topicName, consumerGroup, handler, options) => {
|
|
1676
|
+
const api = getApi(this);
|
|
1677
|
+
const topic = new Topic(api, topicName);
|
|
1678
|
+
const visibilityTimeoutSeconds = options && "visibilityTimeoutSeconds" in options ? options.visibilityTimeoutSeconds : void 0;
|
|
1679
|
+
const consumer = topic.consumerGroup(
|
|
1680
|
+
consumerGroup,
|
|
1681
|
+
visibilityTimeoutSeconds !== void 0 ? { visibilityTimeoutSeconds } : {}
|
|
1682
|
+
);
|
|
1683
|
+
try {
|
|
1684
|
+
let count;
|
|
1685
|
+
const retry = options?.retry;
|
|
1686
|
+
if (options && "messageId" in options) {
|
|
1687
|
+
count = await consumer.consume(handler, {
|
|
1688
|
+
messageId: options.messageId,
|
|
1689
|
+
retry
|
|
1690
|
+
});
|
|
1691
|
+
} else {
|
|
1692
|
+
const limit = options && "limit" in options ? options.limit : void 0;
|
|
1693
|
+
count = await consumer.consume(handler, {
|
|
1694
|
+
...limit !== void 0 ? { limit } : {},
|
|
1695
|
+
retry
|
|
1696
|
+
});
|
|
1697
|
+
}
|
|
1698
|
+
if (count === 0) {
|
|
1699
|
+
return { ok: false, reason: "empty" };
|
|
1700
|
+
}
|
|
1701
|
+
return { ok: true };
|
|
1702
|
+
} catch (error) {
|
|
1703
|
+
if (options && "messageId" in options && error instanceof MessageNotFoundError) {
|
|
1704
|
+
return { ok: false, reason: "not_found", messageId: options.messageId };
|
|
1705
|
+
}
|
|
1706
|
+
if (options && "messageId" in options && error instanceof MessageNotAvailableError) {
|
|
1707
|
+
return {
|
|
1708
|
+
ok: false,
|
|
1709
|
+
reason: "not_available",
|
|
1710
|
+
messageId: options.messageId
|
|
1711
|
+
};
|
|
1712
|
+
}
|
|
1713
|
+
if (options && "messageId" in options && error instanceof MessageAlreadyProcessedError) {
|
|
1714
|
+
return {
|
|
1715
|
+
ok: false,
|
|
1716
|
+
reason: "already_processed",
|
|
1717
|
+
messageId: options.messageId
|
|
1718
|
+
};
|
|
1719
|
+
}
|
|
1720
|
+
throw error;
|
|
1721
|
+
}
|
|
1722
|
+
};
|
|
1723
|
+
};
|
|
1677
1724
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1678
1725
|
0 && (module.exports = {
|
|
1679
1726
|
BadRequestError,
|
|
@@ -1692,6 +1739,7 @@ var QueueClient = class {
|
|
|
1692
1739
|
MessageLockedError,
|
|
1693
1740
|
MessageNotAvailableError,
|
|
1694
1741
|
MessageNotFoundError,
|
|
1742
|
+
PollingQueueClient,
|
|
1695
1743
|
QueueClient,
|
|
1696
1744
|
QueueEmptyError,
|
|
1697
1745
|
StreamTransport,
|