@vercel/queue 0.0.0-alpha.37 → 0.0.0-alpha.38
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 +208 -168
- package/dist/{types-CAA8nT8x.d.mts → callback-lq_sorrn.d.mts} +249 -16
- package/dist/{types-CAA8nT8x.d.ts → callback-lq_sorrn.d.ts} +249 -16
- package/dist/index.d.mts +74 -333
- package/dist/index.d.ts +74 -333
- package/dist/index.js +713 -679
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +709 -678
- package/dist/index.mjs.map +1 -1
- package/dist/nextjs-pages.d.mts +47 -27
- package/dist/nextjs-pages.d.ts +47 -27
- package/dist/nextjs-pages.js +320 -313
- package/dist/nextjs-pages.js.map +1 -1
- package/dist/nextjs-pages.mjs +320 -313
- package/dist/nextjs-pages.mjs.map +1 -1
- package/dist/web.d.mts +60 -0
- package/dist/web.d.ts +60 -0
- package/dist/web.js +1457 -0
- package/dist/web.js.map +1 -0
- package/dist/web.mjs +1420 -0
- package/dist/web.mjs.map +1 -0
- package/package.json +11 -1
package/README.md
CHANGED
|
@@ -5,12 +5,13 @@ A TypeScript client library for interacting with the Vercel Queue Service API, d
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Automatic Queue Triggering**: Vercel automatically triggers your API routes when messages are ready
|
|
8
|
-
- **Next.js Integration**: Built-in support for Next.js
|
|
8
|
+
- **Next.js Integration**: Built-in support for Next.js App Router and Pages Router
|
|
9
9
|
- **Generic Payload Support**: Send and receive any type of data with type safety
|
|
10
10
|
- **Pub/Sub Pattern**: Topic-based messaging with consumer groups
|
|
11
11
|
- **Type Safety**: Full TypeScript support with generic types
|
|
12
12
|
- **Streaming Support**: Handle large payloads efficiently
|
|
13
13
|
- **Customizable Serialization**: Use built-in transports (JSON, Buffer, Stream) or create your own
|
|
14
|
+
- **Framework Adapters**: Web API, Next.js App Router, and Pages Router support
|
|
14
15
|
|
|
15
16
|
## Installation
|
|
16
17
|
|
|
@@ -39,6 +40,8 @@ vc env pull
|
|
|
39
40
|
|
|
40
41
|
The library reads your `vercel.json` configuration, discovers your queue handlers, and triggers them automatically when messages are sent.
|
|
41
42
|
|
|
43
|
+
> **Note:** Local dev mode is enabled when `NODE_ENV=development`. Most frameworks (Next.js, etc.) set this automatically when running `npm run dev`.
|
|
44
|
+
|
|
42
45
|
### Example Workflow
|
|
43
46
|
|
|
44
47
|
```bash
|
|
@@ -48,18 +51,6 @@ npm run dev
|
|
|
48
51
|
# Send messages - they process locally automatically!
|
|
49
52
|
```
|
|
50
53
|
|
|
51
|
-
### TypeScript Configuration
|
|
52
|
-
|
|
53
|
-
Update your `tsconfig.json` to use `"bundler"` module resolution for proper package export resolution:
|
|
54
|
-
|
|
55
|
-
```json
|
|
56
|
-
{
|
|
57
|
-
"compilerOptions": {
|
|
58
|
-
"moduleResolution": "bundler"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
54
|
### Publishing Messages
|
|
64
55
|
|
|
65
56
|
The `send` function can be used anywhere in your codebase to publish messages to a queue:
|
|
@@ -109,124 +100,108 @@ Messages are consumed using API routes that Vercel automatically triggers when m
|
|
|
109
100
|
|
|
110
101
|
#### 1. Create API Routes
|
|
111
102
|
|
|
112
|
-
#####
|
|
103
|
+
##### Web API (`@vercel/queue/web`)
|
|
113
104
|
|
|
114
|
-
The
|
|
105
|
+
The `handleCallback` from `@vercel/queue/web` returns a standard `(Request) => Promise<Response>` handler. It works with any framework that uses the Web API `Request`/`Response` types, including Next.js App Router, Hono, and others.
|
|
106
|
+
|
|
107
|
+
**Next.js App Router:**
|
|
115
108
|
|
|
116
109
|
```typescript
|
|
117
|
-
// app/api/queue/route.ts
|
|
118
|
-
import { handleCallback } from "@vercel/queue";
|
|
119
|
-
|
|
120
|
-
export const POST = handleCallback({
|
|
121
|
-
// Single topic with one consumer
|
|
122
|
-
"my-topic": {
|
|
123
|
-
"my-consumer": async (message, metadata) => {
|
|
124
|
-
// metadata includes: { messageId, deliveryCount, createdAt, topicName, consumerGroup }
|
|
125
|
-
console.log("Processing message:", message);
|
|
126
|
-
|
|
127
|
-
// If this throws an error, the message will be automatically retried
|
|
128
|
-
await processMessage(message);
|
|
129
|
-
},
|
|
130
|
-
},
|
|
110
|
+
// app/api/queue/my-topic/route.ts
|
|
111
|
+
import { handleCallback } from "@vercel/queue/web";
|
|
131
112
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
await trackOrder(order);
|
|
139
|
-
},
|
|
140
|
-
},
|
|
113
|
+
export const POST = handleCallback(async (message, metadata) => {
|
|
114
|
+
// metadata includes: { messageId, deliveryCount, createdAt, topicName, consumerGroup }
|
|
115
|
+
console.log("Processing message:", message);
|
|
116
|
+
|
|
117
|
+
// If this throws an error, the message will be automatically retried
|
|
118
|
+
await processMessage(message);
|
|
141
119
|
});
|
|
142
120
|
```
|
|
143
121
|
|
|
144
|
-
|
|
122
|
+
**Hono:**
|
|
145
123
|
|
|
146
|
-
|
|
124
|
+
```typescript
|
|
125
|
+
import { Hono } from "hono";
|
|
126
|
+
import { handleCallback } from "@vercel/queue/web";
|
|
147
127
|
|
|
148
|
-
|
|
128
|
+
const app = new Hono();
|
|
129
|
+
|
|
130
|
+
app.post(
|
|
131
|
+
"/api/queue",
|
|
132
|
+
handleCallback(async (message, metadata) => {
|
|
133
|
+
console.log("Processing:", message);
|
|
134
|
+
}),
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
export default app;
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
For multiple topics/consumers, create separate route files:
|
|
149
141
|
|
|
150
142
|
```typescript
|
|
151
|
-
//
|
|
152
|
-
import { handleCallback } from "@vercel/queue/
|
|
143
|
+
// app/api/queue/orders/fulfillment/route.ts
|
|
144
|
+
import { handleCallback } from "@vercel/queue/web";
|
|
153
145
|
|
|
154
|
-
export
|
|
155
|
-
|
|
156
|
-
"my-consumer": async (message, metadata) => {
|
|
157
|
-
console.log("Processing message:", message);
|
|
158
|
-
await processMessage(message);
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
"order-events": {
|
|
162
|
-
fulfillment: async (order, metadata) => {
|
|
163
|
-
await processOrder(order);
|
|
164
|
-
},
|
|
165
|
-
analytics: async (order, metadata) => {
|
|
166
|
-
await trackOrder(order);
|
|
167
|
-
},
|
|
168
|
-
},
|
|
146
|
+
export const POST = handleCallback(async (order, metadata) => {
|
|
147
|
+
await processOrder(order);
|
|
169
148
|
});
|
|
170
149
|
```
|
|
171
150
|
|
|
172
|
-
|
|
151
|
+
```typescript
|
|
152
|
+
// app/api/queue/orders/analytics/route.ts
|
|
153
|
+
import { handleCallback } from "@vercel/queue/web";
|
|
173
154
|
|
|
174
|
-
|
|
155
|
+
export const POST = handleCallback(async (order, metadata) => {
|
|
156
|
+
await trackOrder(order);
|
|
157
|
+
});
|
|
158
|
+
```
|
|
175
159
|
|
|
176
|
-
|
|
160
|
+
##### Pages Router (`@vercel/queue/nextjs/pages`)
|
|
177
161
|
|
|
178
|
-
|
|
162
|
+
For Next.js Pages Router, import from `@vercel/queue/nextjs/pages`. This returns a `(req, res) => Promise<void>` handler:
|
|
179
163
|
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
"consumer": "my-consumer",
|
|
189
|
-
"retryAfterSeconds": 60,
|
|
190
|
-
"initialDelaySeconds": 0
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
"type": "queue/v1beta",
|
|
194
|
-
"topic": "order-events",
|
|
195
|
-
"consumer": "fulfillment"
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
"type": "queue/v1beta",
|
|
199
|
-
"topic": "order-events",
|
|
200
|
-
"consumer": "analytics",
|
|
201
|
-
"retryAfterSeconds": 300
|
|
202
|
-
}
|
|
203
|
-
]
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
164
|
+
```typescript
|
|
165
|
+
// pages/api/queue/my-topic.ts
|
|
166
|
+
import { handleCallback } from "@vercel/queue/nextjs/pages";
|
|
167
|
+
|
|
168
|
+
export default handleCallback(async (message, metadata) => {
|
|
169
|
+
console.log("Processing message:", message);
|
|
170
|
+
await processMessage(message);
|
|
171
|
+
});
|
|
207
172
|
```
|
|
208
173
|
|
|
209
|
-
|
|
174
|
+
#### 2. Configure vercel.json
|
|
175
|
+
|
|
176
|
+
Configure which topics and consumers your API routes handle.
|
|
210
177
|
|
|
211
178
|
```json
|
|
212
179
|
{
|
|
213
180
|
"functions": {
|
|
214
|
-
"
|
|
181
|
+
"app/api/queue/my-topic/route.ts": {
|
|
215
182
|
"experimentalTriggers": [
|
|
216
183
|
{
|
|
217
|
-
"type": "queue/
|
|
184
|
+
"type": "queue/v2beta",
|
|
218
185
|
"topic": "my-topic",
|
|
219
186
|
"consumer": "my-consumer",
|
|
220
187
|
"retryAfterSeconds": 60,
|
|
221
188
|
"initialDelaySeconds": 0
|
|
222
|
-
}
|
|
189
|
+
}
|
|
190
|
+
]
|
|
191
|
+
},
|
|
192
|
+
"app/api/queue/orders/fulfillment/route.ts": {
|
|
193
|
+
"experimentalTriggers": [
|
|
223
194
|
{
|
|
224
|
-
"type": "queue/
|
|
195
|
+
"type": "queue/v2beta",
|
|
225
196
|
"topic": "order-events",
|
|
226
197
|
"consumer": "fulfillment"
|
|
227
|
-
}
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
},
|
|
201
|
+
"app/api/queue/orders/analytics/route.ts": {
|
|
202
|
+
"experimentalTriggers": [
|
|
228
203
|
{
|
|
229
|
-
"type": "queue/
|
|
204
|
+
"type": "queue/v2beta",
|
|
230
205
|
"topic": "order-events",
|
|
231
206
|
"consumer": "analytics",
|
|
232
207
|
"retryAfterSeconds": 300
|
|
@@ -246,47 +221,48 @@ Configure which topics and consumers your API route handles.
|
|
|
246
221
|
- **Automatic Triggering**: Vercel triggers your API routes when messages are available
|
|
247
222
|
- **Message Processing**: Your API routes receive message metadata via headers
|
|
248
223
|
- **Configuration**: The `vercel.json` file tells Vercel which routes handle which topics/consumers
|
|
224
|
+
- **Delivery Modes**: The server uses CloudEvents binary content mode to deliver messages. For small messages, the full payload and receipt handle are pushed directly in the HTTP body and headers, avoiding an extra API fetch. For large messages, only the message ID is sent and the SDK fetches the payload.
|
|
249
225
|
|
|
250
226
|
## Advanced Features
|
|
251
227
|
|
|
252
|
-
### Client
|
|
228
|
+
### Custom Client Configuration
|
|
253
229
|
|
|
254
|
-
For custom configuration (tokens, headers,
|
|
230
|
+
For custom configuration (tokens, headers, transport), create a `QueueClient` and pass it via options:
|
|
255
231
|
|
|
256
232
|
```typescript
|
|
257
|
-
import {
|
|
233
|
+
import { QueueClient, send } from "@vercel/queue";
|
|
234
|
+
import { handleCallback } from "@vercel/queue/web";
|
|
258
235
|
|
|
259
|
-
const client = new
|
|
260
|
-
token: "my-token",
|
|
261
|
-
headers: { "X-Custom": "header" },
|
|
262
|
-
pinToDeployment: false, // Optional: disable deployment pinning (default: true)
|
|
236
|
+
const client = new QueueClient({
|
|
237
|
+
token: "my-token",
|
|
238
|
+
headers: { "X-Custom": "header" },
|
|
263
239
|
});
|
|
264
240
|
|
|
265
|
-
// Send
|
|
266
|
-
await
|
|
241
|
+
// Send with custom client
|
|
242
|
+
await send("my-topic", { hello: "world" }, { client });
|
|
267
243
|
|
|
268
|
-
// Handle callbacks
|
|
269
|
-
export const POST =
|
|
270
|
-
|
|
271
|
-
"my-group": async (msg, meta) => console.log(msg),
|
|
272
|
-
},
|
|
244
|
+
// Handle callbacks with custom client
|
|
245
|
+
export const POST = handleCallback(async (msg, meta) => console.log(msg), {
|
|
246
|
+
client,
|
|
273
247
|
});
|
|
274
248
|
```
|
|
275
249
|
|
|
276
|
-
###
|
|
250
|
+
### Core Handler (Framework Agnostic)
|
|
277
251
|
|
|
278
|
-
For custom
|
|
252
|
+
For custom framework integration, use the core `handleCallback` from `@vercel/queue`. It takes parsed request data and throws on errors:
|
|
279
253
|
|
|
280
254
|
```typescript
|
|
281
|
-
import {
|
|
282
|
-
|
|
283
|
-
export async function POST(request: Request) {
|
|
284
|
-
const { queueName, consumerGroup, messageId } = await parseCallback(request);
|
|
285
|
-
|
|
286
|
-
// Use the parsed information for custom processing...
|
|
287
|
-
await myWorkflow.handleWebhook(queueName, consumerGroup, messageId);
|
|
255
|
+
import { handleCallback, parseRawCallback } from "@vercel/queue";
|
|
288
256
|
|
|
289
|
-
|
|
257
|
+
// In your framework handler:
|
|
258
|
+
const parsed = parseRawCallback(body, headers);
|
|
259
|
+
try {
|
|
260
|
+
await handleCallback(async (msg, meta) => {
|
|
261
|
+
console.log("Processing:", msg);
|
|
262
|
+
}, parsed);
|
|
263
|
+
// success
|
|
264
|
+
} catch (error) {
|
|
265
|
+
// handle error → 500
|
|
290
266
|
}
|
|
291
267
|
```
|
|
292
268
|
|
|
@@ -332,11 +308,41 @@ await send("json-topic", { data: "example" }, { transport });
|
|
|
332
308
|
| Large payloads | StreamTransport | Very Low | Medium |
|
|
333
309
|
| Real-time streams | StreamTransport | Very Low | High |
|
|
334
310
|
|
|
311
|
+
## Handling Empty Queues
|
|
312
|
+
|
|
313
|
+
When no messages are available in the queue, the handler receives `null` for both the message and metadata parameters. This allows graceful handling without exceptions:
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
await receive("my-topic", "my-consumer", async (message, metadata) => {
|
|
317
|
+
if (!message) {
|
|
318
|
+
console.log("No message received - queue is empty");
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Process the message
|
|
323
|
+
console.log("Processing:", message);
|
|
324
|
+
console.log("Message ID:", metadata.messageId);
|
|
325
|
+
});
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
The same pattern works with `handleCallback`:
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
import { handleCallback } from "@vercel/queue/web";
|
|
332
|
+
|
|
333
|
+
export const POST = handleCallback(async (message, metadata) => {
|
|
334
|
+
if (!message) {
|
|
335
|
+
// No message available - handle gracefully
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
await processMessage(message);
|
|
339
|
+
});
|
|
340
|
+
```
|
|
341
|
+
|
|
335
342
|
## Error Handling
|
|
336
343
|
|
|
337
344
|
The queue client provides specific error types:
|
|
338
345
|
|
|
339
|
-
- **`QueueEmptyError`**: No messages available in the queue
|
|
340
346
|
- **`MessageLockedError`**: Message is being processed by another consumer
|
|
341
347
|
- **`MessageNotFoundError`**: Message doesn't exist or has expired
|
|
342
348
|
- **`MessageNotAvailableError`**: Message exists but cannot be claimed
|
|
@@ -399,26 +405,32 @@ The following environment variables can be used to configure the queue client:
|
|
|
399
405
|
```typescript
|
|
400
406
|
import { receive } from "@vercel/queue";
|
|
401
407
|
|
|
402
|
-
// Process next available message
|
|
403
|
-
await receive<T>(topicName, consumerGroup,
|
|
408
|
+
// Process next available message (or null if queue is empty)
|
|
409
|
+
await receive<T>(topicName, consumerGroup, async (message, metadata) => {
|
|
410
|
+
if (!message) {
|
|
411
|
+
console.log("Queue is empty");
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
// Process message
|
|
415
|
+
});
|
|
404
416
|
|
|
405
|
-
//
|
|
417
|
+
// Batch processing: fetch up to 10 messages in one request
|
|
406
418
|
await receive<T>(topicName, consumerGroup, handler, {
|
|
407
|
-
|
|
419
|
+
limit: 10, // Default: 1, Min: 1, Max: 10
|
|
408
420
|
});
|
|
409
421
|
|
|
410
|
-
// Process message
|
|
422
|
+
// Process specific message by ID
|
|
411
423
|
await receive<T>(topicName, consumerGroup, handler, {
|
|
412
|
-
messageId: "message-id",
|
|
413
|
-
transport: new JsonTransport(), // Optional: custom transport (defaults to JsonTransport)
|
|
414
|
-
visibilityTimeoutSeconds: 30, // Optional: message visibility timeout
|
|
415
|
-
visibilityRefreshInterval: 10, // Optional: how often to refresh the lock
|
|
424
|
+
messageId: "message-id",
|
|
416
425
|
});
|
|
417
426
|
|
|
427
|
+
// Note: limit and messageId are mutually exclusive options
|
|
428
|
+
|
|
418
429
|
// Handler function signature
|
|
430
|
+
// When queue is empty, both message and metadata are null
|
|
419
431
|
type MessageHandler<T = unknown> = (
|
|
420
|
-
message: T,
|
|
421
|
-
metadata: MessageMetadata,
|
|
432
|
+
message: T | null,
|
|
433
|
+
metadata: MessageMetadata | null,
|
|
422
434
|
) => Promise<void> | void;
|
|
423
435
|
|
|
424
436
|
// MessageMetadata type
|
|
@@ -437,7 +449,7 @@ interface MessageMetadata {
|
|
|
437
449
|
|
|
438
450
|
| Limit | Value | Notes |
|
|
439
451
|
| --------------------------- | --------------------- | ----------------------------------- |
|
|
440
|
-
| Message throughput | 10,
|
|
452
|
+
| Message throughput | 10,000+ msg/sec/topic | Scales horizontally |
|
|
441
453
|
| Payload size | 1 GB | Smaller messages have lower latency |
|
|
442
454
|
| Number of topics | Unlimited | No hard limit |
|
|
443
455
|
| Consumer groups per message | ~4,000 | Per-message limit |
|
|
@@ -495,7 +507,7 @@ Topic patterns support wildcards for flexible routing:
|
|
|
495
507
|
"app/api/queue/route.ts": {
|
|
496
508
|
"experimentalTriggers": [
|
|
497
509
|
{
|
|
498
|
-
"type": "queue/
|
|
510
|
+
"type": "queue/v2beta",
|
|
499
511
|
"topic": "user-*",
|
|
500
512
|
"consumer": "processor"
|
|
501
513
|
}
|
|
@@ -514,12 +526,28 @@ Topic patterns support wildcards for flexible routing:
|
|
|
514
526
|
|
|
515
527
|
## API Reference
|
|
516
528
|
|
|
517
|
-
###
|
|
529
|
+
### Export Structure
|
|
530
|
+
|
|
531
|
+
| Import Path | `handleCallback` |
|
|
532
|
+
| ---------------------------- | ---------------------------------------------------------------- |
|
|
533
|
+
| `@vercel/queue` | Core async function: `(handler, parsed, opts?) => Promise<void>` |
|
|
534
|
+
| `@vercel/queue/web` | Returns `(request: Request) => Promise<Response>` |
|
|
535
|
+
| `@vercel/queue/nextjs/pages` | Returns `(req, res) => Promise<void>` |
|
|
536
|
+
|
|
537
|
+
Additional exports from `@vercel/queue`:
|
|
538
|
+
|
|
539
|
+
| Export | Description |
|
|
540
|
+
| ------------------------- | ------------------------------------------------------------- |
|
|
541
|
+
| `parseCallback` | Parse a Web API `Request` into a `ParsedCallbackRequest` |
|
|
542
|
+
| `parseRawCallback` | Parse a pre-parsed body + headers (e.g. Pages Router) |
|
|
543
|
+
| `CLOUD_EVENT_TYPE_V2BETA` | `"com.vercel.queue.v2beta"` — binary CloudEvent type constant |
|
|
544
|
+
|
|
545
|
+
### QueueClient Configuration
|
|
518
546
|
|
|
519
547
|
```typescript
|
|
520
|
-
import {
|
|
548
|
+
import { QueueClient } from "@vercel/queue";
|
|
521
549
|
|
|
522
|
-
const client = new
|
|
550
|
+
const client = new QueueClient({
|
|
523
551
|
// Base URL for the queue service
|
|
524
552
|
// Default: "https://vercel-queue.com"
|
|
525
553
|
// Env: VERCEL_QUEUE_BASE_URL
|
|
@@ -544,6 +572,10 @@ const client = new Client({
|
|
|
544
572
|
// Default: true
|
|
545
573
|
pinToDeployment: true,
|
|
546
574
|
});
|
|
575
|
+
|
|
576
|
+
// Pass to any function via options
|
|
577
|
+
await send("my-topic", payload, { client });
|
|
578
|
+
export const POST = handleCallback(handler, { client });
|
|
547
579
|
```
|
|
548
580
|
|
|
549
581
|
### Send Options
|
|
@@ -569,62 +601,70 @@ await send("my-topic", payload, {
|
|
|
569
601
|
|
|
570
602
|
### Receive Options
|
|
571
603
|
|
|
604
|
+
The `receive` function supports two mutually exclusive modes:
|
|
605
|
+
|
|
572
606
|
```typescript
|
|
607
|
+
// Batch mode: receive multiple messages
|
|
573
608
|
await receive("my-topic", "my-consumer", handler, {
|
|
574
|
-
//
|
|
575
|
-
|
|
609
|
+
// Maximum messages to retrieve in a single request
|
|
610
|
+
// Default: 1, Min: 1, Max: 10
|
|
611
|
+
limit: 10,
|
|
576
612
|
|
|
577
613
|
// Message lock duration in seconds
|
|
578
|
-
// Default:
|
|
614
|
+
// Default: 300, Min: 30, Max: 3600
|
|
579
615
|
visibilityTimeoutSeconds: 60,
|
|
580
|
-
|
|
581
|
-
// How often to refresh the lock during processing
|
|
582
|
-
// Default: visibilityTimeoutSeconds / 3
|
|
583
|
-
visibilityRefreshInterval: 15,
|
|
584
|
-
|
|
585
|
-
// Custom deserializer (default: JsonTransport)
|
|
586
|
-
transport: new JsonTransport(),
|
|
587
616
|
});
|
|
588
|
-
```
|
|
589
|
-
|
|
590
|
-
### Receive Options (Advanced)
|
|
591
617
|
|
|
592
|
-
|
|
618
|
+
// By-ID mode: receive a specific message
|
|
593
619
|
await receive("my-topic", "my-consumer", handler, {
|
|
594
|
-
//
|
|
595
|
-
|
|
596
|
-
transport: new JsonTransport(),
|
|
620
|
+
// Specific message ID to consume
|
|
621
|
+
messageId: "0-1",
|
|
597
622
|
|
|
598
|
-
// Message lock duration
|
|
599
|
-
// Default:
|
|
623
|
+
// Message lock duration in seconds
|
|
624
|
+
// Default: 300, Min: 30, Max: 3600
|
|
600
625
|
visibilityTimeoutSeconds: 60,
|
|
601
|
-
|
|
602
|
-
// How often to refresh the lock during processing
|
|
603
|
-
// Default: visibilityTimeoutSeconds / 3
|
|
604
|
-
visibilityRefreshInterval: 20,
|
|
605
626
|
});
|
|
606
627
|
```
|
|
607
628
|
|
|
629
|
+
> **Note**: `limit` and `messageId` cannot be used together - they are mutually exclusive options.
|
|
630
|
+
|
|
608
631
|
### handleCallback Options
|
|
609
632
|
|
|
610
633
|
```typescript
|
|
634
|
+
import { handleCallback } from "@vercel/queue/web";
|
|
635
|
+
|
|
611
636
|
export const POST = handleCallback(
|
|
612
|
-
{
|
|
613
|
-
|
|
614
|
-
"my-consumer": async (message, metadata) => {
|
|
615
|
-
await processMessage(message);
|
|
616
|
-
},
|
|
617
|
-
},
|
|
637
|
+
async (message, metadata) => {
|
|
638
|
+
await processMessage(message);
|
|
618
639
|
},
|
|
619
640
|
{
|
|
620
641
|
// Message lock duration for long-running handlers
|
|
621
|
-
// Default:
|
|
622
|
-
// visibilityRefreshInterval defaults to visibilityTimeoutSeconds / 3
|
|
642
|
+
// Default: 300, Min: 30, Max: 3600
|
|
623
643
|
visibilityTimeoutSeconds: 300, // 5 minutes
|
|
624
644
|
},
|
|
625
645
|
);
|
|
626
646
|
```
|
|
627
647
|
|
|
648
|
+
### Core handleCallback
|
|
649
|
+
|
|
650
|
+
The core `handleCallback` is an async function that takes already-parsed request data. Use it to build custom framework integrations:
|
|
651
|
+
|
|
652
|
+
```typescript
|
|
653
|
+
import { handleCallback, parseCallback, parseRawCallback } from "@vercel/queue";
|
|
654
|
+
|
|
655
|
+
// Web API Request
|
|
656
|
+
const parsed = await parseCallback(request);
|
|
657
|
+
|
|
658
|
+
// Or, for frameworks that pre-parse the body (e.g. Pages Router)
|
|
659
|
+
const parsed = parseRawCallback(req.body, req.headers);
|
|
660
|
+
|
|
661
|
+
try {
|
|
662
|
+
await handleCallback(handler, parsed);
|
|
663
|
+
} catch (error) {
|
|
664
|
+
// handle error → 500
|
|
665
|
+
}
|
|
666
|
+
```
|
|
667
|
+
|
|
628
668
|
## License
|
|
629
669
|
|
|
630
670
|
MIT
|