runlater-js 0.11.0 → 0.13.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 +58 -2
- package/dist/index.d.mts +119 -18
- package/dist/index.d.ts +119 -18
- package/dist/index.js +144 -13
- package/dist/index.mjs +144 -13
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# runlater-js
|
|
2
2
|
|
|
3
|
-
Official Node.js SDK for [Runlater](https://runlater.eu) — delayed tasks, cron jobs, and reliable webhooks for any Node.js app. No Redis. No infrastructure. Just HTTP.
|
|
3
|
+
Official Node.js SDK for [Runlater](https://runlater.eu) — delayed tasks, cron jobs, message queues, and reliable webhooks for any Node.js app. No Redis. No infrastructure. Just HTTP.
|
|
4
4
|
|
|
5
5
|
[Documentation](https://runlater.eu/docs) | [Dashboard](https://runlater.eu) | [npm](https://www.npmjs.com/package/runlater-js)
|
|
6
6
|
|
|
@@ -63,7 +63,7 @@ const result = await rl.send("https://myapp.com/api/webhook", {
|
|
|
63
63
|
body: { key: "value" }, // automatically JSON-serialized
|
|
64
64
|
retries: 5, // default: server default
|
|
65
65
|
timeout: 30000, // ms, default: 30000
|
|
66
|
-
|
|
66
|
+
lane: "emails", // optional: serialize execution within a lane
|
|
67
67
|
callback: "https://myapp.com/api/on-complete", // optional: receive result
|
|
68
68
|
})
|
|
69
69
|
// => { task_id, execution_id, status, scheduled_for }
|
|
@@ -129,6 +129,62 @@ const executions = await rl.tasks.executions("task-id")
|
|
|
129
129
|
await rl.tasks.delete("task-id")
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
+
### Message queues
|
|
133
|
+
|
|
134
|
+
Produce and consume messages with at-least-once delivery, visibility timeout, and dead-letter support.
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
// Create a queue
|
|
138
|
+
const queue = await rl.queues.create({
|
|
139
|
+
name: "order-events",
|
|
140
|
+
visibility_timeout_seconds: 30,
|
|
141
|
+
max_receives: 5,
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
// Enqueue a message
|
|
145
|
+
await rl.queues.enqueue("order-events", { orderId: 123, action: "process" })
|
|
146
|
+
|
|
147
|
+
// Enqueue multiple messages
|
|
148
|
+
await rl.queues.enqueueBatch("order-events", [
|
|
149
|
+
{ orderId: 124, action: "process" },
|
|
150
|
+
{ orderId: 125, action: "process" },
|
|
151
|
+
])
|
|
152
|
+
|
|
153
|
+
// Receive messages (long-polling supported)
|
|
154
|
+
const messages = await rl.queues.receive("order-events", { max: 5, wait: 10 })
|
|
155
|
+
|
|
156
|
+
for (const msg of messages) {
|
|
157
|
+
// Process the message...
|
|
158
|
+
console.log(msg.body)
|
|
159
|
+
|
|
160
|
+
// Acknowledge when done
|
|
161
|
+
await rl.queues.ack("order-events", msg.receipt_handle)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Nack a message to release it back to the queue
|
|
165
|
+
await rl.queues.nack("order-events", msg.receipt_handle)
|
|
166
|
+
|
|
167
|
+
// Batch acknowledge
|
|
168
|
+
await rl.queues.ackBatch("order-events", ["receipt_1", "receipt_2"])
|
|
169
|
+
|
|
170
|
+
// Get queue stats
|
|
171
|
+
const stats = await rl.queues.stats("order-events")
|
|
172
|
+
// => { available, locked, completed, dead, total, avg_time_in_queue_seconds, avg_processing_time_seconds }
|
|
173
|
+
|
|
174
|
+
// List all queues
|
|
175
|
+
const queues = await rl.queues.list()
|
|
176
|
+
|
|
177
|
+
// Pause / resume
|
|
178
|
+
await rl.queues.pause("order-events")
|
|
179
|
+
await rl.queues.resume("order-events")
|
|
180
|
+
|
|
181
|
+
// Browse messages
|
|
182
|
+
const msgs = await rl.queues.messages("order-events", { status: "available", limit: 10 })
|
|
183
|
+
|
|
184
|
+
// Delete a queue
|
|
185
|
+
await rl.queues.delete("order-events")
|
|
186
|
+
```
|
|
187
|
+
|
|
132
188
|
### Monitors (dead man's switch)
|
|
133
189
|
|
|
134
190
|
```js
|
package/dist/index.d.mts
CHANGED
|
@@ -8,7 +8,7 @@ interface SendOptions {
|
|
|
8
8
|
body?: unknown;
|
|
9
9
|
retries?: number;
|
|
10
10
|
timeout?: number;
|
|
11
|
-
|
|
11
|
+
lane?: string;
|
|
12
12
|
callback?: string;
|
|
13
13
|
idempotencyKey?: string;
|
|
14
14
|
on_failure_url?: string;
|
|
@@ -31,7 +31,7 @@ interface CronOptions {
|
|
|
31
31
|
body?: unknown;
|
|
32
32
|
timeout?: number;
|
|
33
33
|
retries?: number;
|
|
34
|
-
|
|
34
|
+
lane?: string;
|
|
35
35
|
callback?: string;
|
|
36
36
|
enabled?: boolean;
|
|
37
37
|
on_failure_url?: string;
|
|
@@ -126,7 +126,7 @@ interface Task {
|
|
|
126
126
|
timeout_ms: number;
|
|
127
127
|
retry_attempts: number;
|
|
128
128
|
callback_url: string | null;
|
|
129
|
-
|
|
129
|
+
lane: string | null;
|
|
130
130
|
notify_on_failure: boolean | null;
|
|
131
131
|
notify_on_recovery: boolean | null;
|
|
132
132
|
on_failure_url: string | null;
|
|
@@ -149,7 +149,7 @@ interface Execution {
|
|
|
149
149
|
script_logs: string[];
|
|
150
150
|
}
|
|
151
151
|
interface ListOptions {
|
|
152
|
-
|
|
152
|
+
lane?: string;
|
|
153
153
|
limit?: number;
|
|
154
154
|
offset?: number;
|
|
155
155
|
}
|
|
@@ -192,7 +192,7 @@ interface BatchTask {
|
|
|
192
192
|
name?: string;
|
|
193
193
|
}
|
|
194
194
|
interface BatchOptions {
|
|
195
|
-
|
|
195
|
+
lane: string;
|
|
196
196
|
tasks: BatchTask[];
|
|
197
197
|
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
198
198
|
headers?: Record<string, string>;
|
|
@@ -203,11 +203,11 @@ interface BatchOptions {
|
|
|
203
203
|
callback?: string;
|
|
204
204
|
}
|
|
205
205
|
interface BatchResponse {
|
|
206
|
-
|
|
206
|
+
lane: string;
|
|
207
207
|
created: number;
|
|
208
208
|
scheduled_for: string;
|
|
209
209
|
}
|
|
210
|
-
interface
|
|
210
|
+
interface CancelLaneResponse {
|
|
211
211
|
cancelled: number;
|
|
212
212
|
}
|
|
213
213
|
interface UpdateTaskOptions {
|
|
@@ -221,7 +221,7 @@ interface UpdateTaskOptions {
|
|
|
221
221
|
timeout_ms?: number;
|
|
222
222
|
retry_attempts?: number;
|
|
223
223
|
callback_url?: string;
|
|
224
|
-
|
|
224
|
+
lane?: string;
|
|
225
225
|
enabled?: boolean;
|
|
226
226
|
notify_on_failure?: boolean | null;
|
|
227
227
|
notify_on_recovery?: boolean | null;
|
|
@@ -289,7 +289,7 @@ interface Endpoint {
|
|
|
289
289
|
enabled: boolean;
|
|
290
290
|
paused: boolean;
|
|
291
291
|
retry_attempts: number;
|
|
292
|
-
|
|
292
|
+
use_lane: boolean;
|
|
293
293
|
notify_on_failure: boolean | null;
|
|
294
294
|
notify_on_recovery: boolean | null;
|
|
295
295
|
on_failure_url: string | null;
|
|
@@ -306,7 +306,7 @@ interface CreateEndpointOptions {
|
|
|
306
306
|
name: string;
|
|
307
307
|
forward_urls: string[];
|
|
308
308
|
retry_attempts?: number;
|
|
309
|
-
|
|
309
|
+
use_lane?: boolean;
|
|
310
310
|
enabled?: boolean;
|
|
311
311
|
forward_headers?: Record<string, string>;
|
|
312
312
|
forward_body?: string;
|
|
@@ -318,7 +318,7 @@ interface UpdateEndpointOptions {
|
|
|
318
318
|
name?: string;
|
|
319
319
|
forward_urls?: string[];
|
|
320
320
|
retry_attempts?: number;
|
|
321
|
-
|
|
321
|
+
use_lane?: boolean;
|
|
322
322
|
enabled?: boolean;
|
|
323
323
|
forward_headers?: Record<string, string>;
|
|
324
324
|
forward_body?: string;
|
|
@@ -335,6 +335,66 @@ interface InboundEvent {
|
|
|
335
335
|
lua_rejected: boolean;
|
|
336
336
|
lua_logs: string[];
|
|
337
337
|
}
|
|
338
|
+
interface MessageQueue {
|
|
339
|
+
id: string;
|
|
340
|
+
name: string;
|
|
341
|
+
slug: string;
|
|
342
|
+
visibility_timeout_seconds: number;
|
|
343
|
+
max_receives: number;
|
|
344
|
+
paused: boolean;
|
|
345
|
+
inserted_at: string;
|
|
346
|
+
updated_at: string;
|
|
347
|
+
}
|
|
348
|
+
interface CreateMessageQueueOptions {
|
|
349
|
+
name: string;
|
|
350
|
+
visibility_timeout_seconds?: number;
|
|
351
|
+
max_receives?: number;
|
|
352
|
+
}
|
|
353
|
+
interface UpdateMessageQueueOptions {
|
|
354
|
+
name?: string;
|
|
355
|
+
visibility_timeout_seconds?: number;
|
|
356
|
+
max_receives?: number;
|
|
357
|
+
}
|
|
358
|
+
interface MqMessage {
|
|
359
|
+
id: string;
|
|
360
|
+
body: unknown;
|
|
361
|
+
status: string;
|
|
362
|
+
run_at: string | null;
|
|
363
|
+
receipt_handle: string | null;
|
|
364
|
+
receive_count: number;
|
|
365
|
+
locked_until: string | null;
|
|
366
|
+
first_received_at: string | null;
|
|
367
|
+
completed_at: string | null;
|
|
368
|
+
inserted_at: string;
|
|
369
|
+
}
|
|
370
|
+
interface MqEnqueueOptions {
|
|
371
|
+
/** Delay before the message becomes available. Supports "30s", "5m", "2h", "1d" or seconds as number. Max 7 days. Mutually exclusive with run_at. */
|
|
372
|
+
delay?: string | number;
|
|
373
|
+
/** ISO 8601 datetime when the message becomes available. Must be future, max 7 days. Mutually exclusive with delay. */
|
|
374
|
+
run_at?: string;
|
|
375
|
+
}
|
|
376
|
+
interface MqStats {
|
|
377
|
+
available: number;
|
|
378
|
+
locked: number;
|
|
379
|
+
completed: number;
|
|
380
|
+
dead: number;
|
|
381
|
+
total: number;
|
|
382
|
+
avg_time_in_queue_seconds: number | null;
|
|
383
|
+
avg_processing_time_seconds: number | null;
|
|
384
|
+
}
|
|
385
|
+
interface MqReceiveOptions {
|
|
386
|
+
max?: number;
|
|
387
|
+
wait?: number;
|
|
388
|
+
}
|
|
389
|
+
interface MqListMessagesOptions {
|
|
390
|
+
status?: string;
|
|
391
|
+
limit?: number;
|
|
392
|
+
offset?: number;
|
|
393
|
+
}
|
|
394
|
+
interface MqBatchAckResponse {
|
|
395
|
+
acknowledged: number;
|
|
396
|
+
failed: number;
|
|
397
|
+
}
|
|
338
398
|
declare class RunlaterError extends Error {
|
|
339
399
|
status: number;
|
|
340
400
|
code: string;
|
|
@@ -348,6 +408,7 @@ declare class Runlater {
|
|
|
348
408
|
monitors: Monitors;
|
|
349
409
|
endpoints: Endpoints;
|
|
350
410
|
schedules: Schedules;
|
|
411
|
+
queues: MessageQueues;
|
|
351
412
|
constructor(options: RunlaterOptions | string);
|
|
352
413
|
/**
|
|
353
414
|
* Send a request immediately with reliable delivery and retries.
|
|
@@ -433,11 +494,11 @@ declare class Tasks {
|
|
|
433
494
|
* optionally override method, headers, body, and name. Top-level
|
|
434
495
|
* settings serve as defaults.
|
|
435
496
|
*
|
|
436
|
-
* Use the
|
|
497
|
+
* Use the lane name with `cancelLane()` to cancel them as a group.
|
|
437
498
|
*
|
|
438
499
|
* ```js
|
|
439
500
|
* await rl.tasks.batch({
|
|
440
|
-
*
|
|
501
|
+
* lane: "march-newsletter",
|
|
441
502
|
* method: "POST",
|
|
442
503
|
* run_at: "2026-03-01T09:00:00Z",
|
|
443
504
|
* tasks: [
|
|
@@ -449,16 +510,16 @@ declare class Tasks {
|
|
|
449
510
|
*/
|
|
450
511
|
batch(options: BatchOptions): Promise<BatchResponse>;
|
|
451
512
|
/**
|
|
452
|
-
* Cancel all tasks in a
|
|
513
|
+
* Cancel all tasks in a lane.
|
|
453
514
|
*
|
|
454
|
-
* Soft-deletes every task in the
|
|
515
|
+
* Soft-deletes every task in the lane and removes their pending executions.
|
|
455
516
|
*
|
|
456
517
|
* ```js
|
|
457
|
-
* const { cancelled } = await rl.tasks.
|
|
518
|
+
* const { cancelled } = await rl.tasks.cancelLane("march-newsletter")
|
|
458
519
|
* console.log(`Cancelled ${cancelled} tasks`)
|
|
459
520
|
* ```
|
|
460
521
|
*/
|
|
461
|
-
|
|
522
|
+
cancelLane(lane: string): Promise<CancelLaneResponse>;
|
|
462
523
|
}
|
|
463
524
|
declare class Schedules {
|
|
464
525
|
private client;
|
|
@@ -495,5 +556,45 @@ declare class Endpoints {
|
|
|
495
556
|
pause(id: string): Promise<Endpoint>;
|
|
496
557
|
resume(id: string): Promise<Endpoint>;
|
|
497
558
|
}
|
|
559
|
+
declare class MessageQueues {
|
|
560
|
+
private client;
|
|
561
|
+
constructor(client: Runlater);
|
|
562
|
+
/** List all message queues. */
|
|
563
|
+
list(): Promise<MessageQueue[]>;
|
|
564
|
+
/** Create a new message queue. */
|
|
565
|
+
create(options: CreateMessageQueueOptions): Promise<MessageQueue>;
|
|
566
|
+
/** Get a message queue by slug. */
|
|
567
|
+
get(slug: string): Promise<MessageQueue>;
|
|
568
|
+
/** Update a message queue. */
|
|
569
|
+
update(slug: string, options: UpdateMessageQueueOptions): Promise<MessageQueue>;
|
|
570
|
+
/** Delete a message queue. */
|
|
571
|
+
delete(slug: string): Promise<void>;
|
|
572
|
+
/** Get queue statistics. */
|
|
573
|
+
stats(slug: string): Promise<MqStats>;
|
|
574
|
+
/** Enqueue a single message. Optionally delay or schedule for a future time. */
|
|
575
|
+
enqueue(slug: string, body: unknown, options?: MqEnqueueOptions): Promise<MqMessage>;
|
|
576
|
+
/** Enqueue multiple messages at once. Each message can have its own delay/run_at. */
|
|
577
|
+
enqueueBatch(slug: string, messages: Array<{
|
|
578
|
+
body: unknown;
|
|
579
|
+
} & MqEnqueueOptions>): Promise<{
|
|
580
|
+
enqueued: number;
|
|
581
|
+
}>;
|
|
582
|
+
/** Receive messages from the queue. */
|
|
583
|
+
receive(slug: string, options?: MqReceiveOptions): Promise<MqMessage[]>;
|
|
584
|
+
/** Acknowledge (complete) a message by receipt handle. */
|
|
585
|
+
ack(slug: string, receiptHandle: string): Promise<void>;
|
|
586
|
+
/** Nack (release) a message back to the queue. */
|
|
587
|
+
nack(slug: string, receiptHandle: string): Promise<void>;
|
|
588
|
+
/** Acknowledge multiple messages at once. */
|
|
589
|
+
ackBatch(slug: string, receiptHandles: string[]): Promise<MqBatchAckResponse>;
|
|
590
|
+
/** List messages in the queue with optional filtering. */
|
|
591
|
+
messages(slug: string, options?: MqListMessagesOptions): Promise<MqMessage[]>;
|
|
592
|
+
/** Get a specific message by ID. */
|
|
593
|
+
getMessage(slug: string, id: string): Promise<MqMessage>;
|
|
594
|
+
/** Pause the queue. */
|
|
595
|
+
pause(slug: string): Promise<MessageQueue>;
|
|
596
|
+
/** Resume a paused queue. */
|
|
597
|
+
resume(slug: string): Promise<MessageQueue>;
|
|
598
|
+
}
|
|
498
599
|
|
|
499
|
-
export { type BatchOptions, type BatchResponse, type BatchTask, type
|
|
600
|
+
export { type BatchOptions, type BatchResponse, type BatchTask, type CancelLaneResponse, type CreateEndpointOptions, type CreateMessageQueueOptions, type CreateMonitorOptions, type CreateScheduleOptions, type CronOptions, type CronResponse, type DelayOptions, type Endpoint, type Execution, type InboundEvent, type ListOptions, type ListResponse, type MessageQueue, type Monitor, type MqBatchAckResponse, type MqEnqueueOptions, type MqListMessagesOptions, type MqMessage, type MqReceiveOptions, type MqStats, type Ping, type PingResponse, Runlater, RunlaterError, type RunlaterOptions, type Schedule, type ScheduleOptions, type SendOptions, type SyncOptions, type SyncResponse, type Task, type TaskResponse, type TriggerResponse, type UpdateEndpointOptions, type UpdateMessageQueueOptions, type UpdateMonitorOptions, type UpdateScheduleOptions, type UpdateTaskOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ interface SendOptions {
|
|
|
8
8
|
body?: unknown;
|
|
9
9
|
retries?: number;
|
|
10
10
|
timeout?: number;
|
|
11
|
-
|
|
11
|
+
lane?: string;
|
|
12
12
|
callback?: string;
|
|
13
13
|
idempotencyKey?: string;
|
|
14
14
|
on_failure_url?: string;
|
|
@@ -31,7 +31,7 @@ interface CronOptions {
|
|
|
31
31
|
body?: unknown;
|
|
32
32
|
timeout?: number;
|
|
33
33
|
retries?: number;
|
|
34
|
-
|
|
34
|
+
lane?: string;
|
|
35
35
|
callback?: string;
|
|
36
36
|
enabled?: boolean;
|
|
37
37
|
on_failure_url?: string;
|
|
@@ -126,7 +126,7 @@ interface Task {
|
|
|
126
126
|
timeout_ms: number;
|
|
127
127
|
retry_attempts: number;
|
|
128
128
|
callback_url: string | null;
|
|
129
|
-
|
|
129
|
+
lane: string | null;
|
|
130
130
|
notify_on_failure: boolean | null;
|
|
131
131
|
notify_on_recovery: boolean | null;
|
|
132
132
|
on_failure_url: string | null;
|
|
@@ -149,7 +149,7 @@ interface Execution {
|
|
|
149
149
|
script_logs: string[];
|
|
150
150
|
}
|
|
151
151
|
interface ListOptions {
|
|
152
|
-
|
|
152
|
+
lane?: string;
|
|
153
153
|
limit?: number;
|
|
154
154
|
offset?: number;
|
|
155
155
|
}
|
|
@@ -192,7 +192,7 @@ interface BatchTask {
|
|
|
192
192
|
name?: string;
|
|
193
193
|
}
|
|
194
194
|
interface BatchOptions {
|
|
195
|
-
|
|
195
|
+
lane: string;
|
|
196
196
|
tasks: BatchTask[];
|
|
197
197
|
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
198
198
|
headers?: Record<string, string>;
|
|
@@ -203,11 +203,11 @@ interface BatchOptions {
|
|
|
203
203
|
callback?: string;
|
|
204
204
|
}
|
|
205
205
|
interface BatchResponse {
|
|
206
|
-
|
|
206
|
+
lane: string;
|
|
207
207
|
created: number;
|
|
208
208
|
scheduled_for: string;
|
|
209
209
|
}
|
|
210
|
-
interface
|
|
210
|
+
interface CancelLaneResponse {
|
|
211
211
|
cancelled: number;
|
|
212
212
|
}
|
|
213
213
|
interface UpdateTaskOptions {
|
|
@@ -221,7 +221,7 @@ interface UpdateTaskOptions {
|
|
|
221
221
|
timeout_ms?: number;
|
|
222
222
|
retry_attempts?: number;
|
|
223
223
|
callback_url?: string;
|
|
224
|
-
|
|
224
|
+
lane?: string;
|
|
225
225
|
enabled?: boolean;
|
|
226
226
|
notify_on_failure?: boolean | null;
|
|
227
227
|
notify_on_recovery?: boolean | null;
|
|
@@ -289,7 +289,7 @@ interface Endpoint {
|
|
|
289
289
|
enabled: boolean;
|
|
290
290
|
paused: boolean;
|
|
291
291
|
retry_attempts: number;
|
|
292
|
-
|
|
292
|
+
use_lane: boolean;
|
|
293
293
|
notify_on_failure: boolean | null;
|
|
294
294
|
notify_on_recovery: boolean | null;
|
|
295
295
|
on_failure_url: string | null;
|
|
@@ -306,7 +306,7 @@ interface CreateEndpointOptions {
|
|
|
306
306
|
name: string;
|
|
307
307
|
forward_urls: string[];
|
|
308
308
|
retry_attempts?: number;
|
|
309
|
-
|
|
309
|
+
use_lane?: boolean;
|
|
310
310
|
enabled?: boolean;
|
|
311
311
|
forward_headers?: Record<string, string>;
|
|
312
312
|
forward_body?: string;
|
|
@@ -318,7 +318,7 @@ interface UpdateEndpointOptions {
|
|
|
318
318
|
name?: string;
|
|
319
319
|
forward_urls?: string[];
|
|
320
320
|
retry_attempts?: number;
|
|
321
|
-
|
|
321
|
+
use_lane?: boolean;
|
|
322
322
|
enabled?: boolean;
|
|
323
323
|
forward_headers?: Record<string, string>;
|
|
324
324
|
forward_body?: string;
|
|
@@ -335,6 +335,66 @@ interface InboundEvent {
|
|
|
335
335
|
lua_rejected: boolean;
|
|
336
336
|
lua_logs: string[];
|
|
337
337
|
}
|
|
338
|
+
interface MessageQueue {
|
|
339
|
+
id: string;
|
|
340
|
+
name: string;
|
|
341
|
+
slug: string;
|
|
342
|
+
visibility_timeout_seconds: number;
|
|
343
|
+
max_receives: number;
|
|
344
|
+
paused: boolean;
|
|
345
|
+
inserted_at: string;
|
|
346
|
+
updated_at: string;
|
|
347
|
+
}
|
|
348
|
+
interface CreateMessageQueueOptions {
|
|
349
|
+
name: string;
|
|
350
|
+
visibility_timeout_seconds?: number;
|
|
351
|
+
max_receives?: number;
|
|
352
|
+
}
|
|
353
|
+
interface UpdateMessageQueueOptions {
|
|
354
|
+
name?: string;
|
|
355
|
+
visibility_timeout_seconds?: number;
|
|
356
|
+
max_receives?: number;
|
|
357
|
+
}
|
|
358
|
+
interface MqMessage {
|
|
359
|
+
id: string;
|
|
360
|
+
body: unknown;
|
|
361
|
+
status: string;
|
|
362
|
+
run_at: string | null;
|
|
363
|
+
receipt_handle: string | null;
|
|
364
|
+
receive_count: number;
|
|
365
|
+
locked_until: string | null;
|
|
366
|
+
first_received_at: string | null;
|
|
367
|
+
completed_at: string | null;
|
|
368
|
+
inserted_at: string;
|
|
369
|
+
}
|
|
370
|
+
interface MqEnqueueOptions {
|
|
371
|
+
/** Delay before the message becomes available. Supports "30s", "5m", "2h", "1d" or seconds as number. Max 7 days. Mutually exclusive with run_at. */
|
|
372
|
+
delay?: string | number;
|
|
373
|
+
/** ISO 8601 datetime when the message becomes available. Must be future, max 7 days. Mutually exclusive with delay. */
|
|
374
|
+
run_at?: string;
|
|
375
|
+
}
|
|
376
|
+
interface MqStats {
|
|
377
|
+
available: number;
|
|
378
|
+
locked: number;
|
|
379
|
+
completed: number;
|
|
380
|
+
dead: number;
|
|
381
|
+
total: number;
|
|
382
|
+
avg_time_in_queue_seconds: number | null;
|
|
383
|
+
avg_processing_time_seconds: number | null;
|
|
384
|
+
}
|
|
385
|
+
interface MqReceiveOptions {
|
|
386
|
+
max?: number;
|
|
387
|
+
wait?: number;
|
|
388
|
+
}
|
|
389
|
+
interface MqListMessagesOptions {
|
|
390
|
+
status?: string;
|
|
391
|
+
limit?: number;
|
|
392
|
+
offset?: number;
|
|
393
|
+
}
|
|
394
|
+
interface MqBatchAckResponse {
|
|
395
|
+
acknowledged: number;
|
|
396
|
+
failed: number;
|
|
397
|
+
}
|
|
338
398
|
declare class RunlaterError extends Error {
|
|
339
399
|
status: number;
|
|
340
400
|
code: string;
|
|
@@ -348,6 +408,7 @@ declare class Runlater {
|
|
|
348
408
|
monitors: Monitors;
|
|
349
409
|
endpoints: Endpoints;
|
|
350
410
|
schedules: Schedules;
|
|
411
|
+
queues: MessageQueues;
|
|
351
412
|
constructor(options: RunlaterOptions | string);
|
|
352
413
|
/**
|
|
353
414
|
* Send a request immediately with reliable delivery and retries.
|
|
@@ -433,11 +494,11 @@ declare class Tasks {
|
|
|
433
494
|
* optionally override method, headers, body, and name. Top-level
|
|
434
495
|
* settings serve as defaults.
|
|
435
496
|
*
|
|
436
|
-
* Use the
|
|
497
|
+
* Use the lane name with `cancelLane()` to cancel them as a group.
|
|
437
498
|
*
|
|
438
499
|
* ```js
|
|
439
500
|
* await rl.tasks.batch({
|
|
440
|
-
*
|
|
501
|
+
* lane: "march-newsletter",
|
|
441
502
|
* method: "POST",
|
|
442
503
|
* run_at: "2026-03-01T09:00:00Z",
|
|
443
504
|
* tasks: [
|
|
@@ -449,16 +510,16 @@ declare class Tasks {
|
|
|
449
510
|
*/
|
|
450
511
|
batch(options: BatchOptions): Promise<BatchResponse>;
|
|
451
512
|
/**
|
|
452
|
-
* Cancel all tasks in a
|
|
513
|
+
* Cancel all tasks in a lane.
|
|
453
514
|
*
|
|
454
|
-
* Soft-deletes every task in the
|
|
515
|
+
* Soft-deletes every task in the lane and removes their pending executions.
|
|
455
516
|
*
|
|
456
517
|
* ```js
|
|
457
|
-
* const { cancelled } = await rl.tasks.
|
|
518
|
+
* const { cancelled } = await rl.tasks.cancelLane("march-newsletter")
|
|
458
519
|
* console.log(`Cancelled ${cancelled} tasks`)
|
|
459
520
|
* ```
|
|
460
521
|
*/
|
|
461
|
-
|
|
522
|
+
cancelLane(lane: string): Promise<CancelLaneResponse>;
|
|
462
523
|
}
|
|
463
524
|
declare class Schedules {
|
|
464
525
|
private client;
|
|
@@ -495,5 +556,45 @@ declare class Endpoints {
|
|
|
495
556
|
pause(id: string): Promise<Endpoint>;
|
|
496
557
|
resume(id: string): Promise<Endpoint>;
|
|
497
558
|
}
|
|
559
|
+
declare class MessageQueues {
|
|
560
|
+
private client;
|
|
561
|
+
constructor(client: Runlater);
|
|
562
|
+
/** List all message queues. */
|
|
563
|
+
list(): Promise<MessageQueue[]>;
|
|
564
|
+
/** Create a new message queue. */
|
|
565
|
+
create(options: CreateMessageQueueOptions): Promise<MessageQueue>;
|
|
566
|
+
/** Get a message queue by slug. */
|
|
567
|
+
get(slug: string): Promise<MessageQueue>;
|
|
568
|
+
/** Update a message queue. */
|
|
569
|
+
update(slug: string, options: UpdateMessageQueueOptions): Promise<MessageQueue>;
|
|
570
|
+
/** Delete a message queue. */
|
|
571
|
+
delete(slug: string): Promise<void>;
|
|
572
|
+
/** Get queue statistics. */
|
|
573
|
+
stats(slug: string): Promise<MqStats>;
|
|
574
|
+
/** Enqueue a single message. Optionally delay or schedule for a future time. */
|
|
575
|
+
enqueue(slug: string, body: unknown, options?: MqEnqueueOptions): Promise<MqMessage>;
|
|
576
|
+
/** Enqueue multiple messages at once. Each message can have its own delay/run_at. */
|
|
577
|
+
enqueueBatch(slug: string, messages: Array<{
|
|
578
|
+
body: unknown;
|
|
579
|
+
} & MqEnqueueOptions>): Promise<{
|
|
580
|
+
enqueued: number;
|
|
581
|
+
}>;
|
|
582
|
+
/** Receive messages from the queue. */
|
|
583
|
+
receive(slug: string, options?: MqReceiveOptions): Promise<MqMessage[]>;
|
|
584
|
+
/** Acknowledge (complete) a message by receipt handle. */
|
|
585
|
+
ack(slug: string, receiptHandle: string): Promise<void>;
|
|
586
|
+
/** Nack (release) a message back to the queue. */
|
|
587
|
+
nack(slug: string, receiptHandle: string): Promise<void>;
|
|
588
|
+
/** Acknowledge multiple messages at once. */
|
|
589
|
+
ackBatch(slug: string, receiptHandles: string[]): Promise<MqBatchAckResponse>;
|
|
590
|
+
/** List messages in the queue with optional filtering. */
|
|
591
|
+
messages(slug: string, options?: MqListMessagesOptions): Promise<MqMessage[]>;
|
|
592
|
+
/** Get a specific message by ID. */
|
|
593
|
+
getMessage(slug: string, id: string): Promise<MqMessage>;
|
|
594
|
+
/** Pause the queue. */
|
|
595
|
+
pause(slug: string): Promise<MessageQueue>;
|
|
596
|
+
/** Resume a paused queue. */
|
|
597
|
+
resume(slug: string): Promise<MessageQueue>;
|
|
598
|
+
}
|
|
498
599
|
|
|
499
|
-
export { type BatchOptions, type BatchResponse, type BatchTask, type
|
|
600
|
+
export { type BatchOptions, type BatchResponse, type BatchTask, type CancelLaneResponse, type CreateEndpointOptions, type CreateMessageQueueOptions, type CreateMonitorOptions, type CreateScheduleOptions, type CronOptions, type CronResponse, type DelayOptions, type Endpoint, type Execution, type InboundEvent, type ListOptions, type ListResponse, type MessageQueue, type Monitor, type MqBatchAckResponse, type MqEnqueueOptions, type MqListMessagesOptions, type MqMessage, type MqReceiveOptions, type MqStats, type Ping, type PingResponse, Runlater, RunlaterError, type RunlaterOptions, type Schedule, type ScheduleOptions, type SendOptions, type SyncOptions, type SyncResponse, type Task, type TaskResponse, type TriggerResponse, type UpdateEndpointOptions, type UpdateMessageQueueOptions, type UpdateMonitorOptions, type UpdateScheduleOptions, type UpdateTaskOptions };
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,7 @@ var Runlater = class {
|
|
|
46
46
|
monitors;
|
|
47
47
|
endpoints;
|
|
48
48
|
schedules;
|
|
49
|
+
queues;
|
|
49
50
|
constructor(options) {
|
|
50
51
|
if (typeof options === "string") {
|
|
51
52
|
this.apiKey = options;
|
|
@@ -58,6 +59,7 @@ var Runlater = class {
|
|
|
58
59
|
this.monitors = new Monitors(this);
|
|
59
60
|
this.endpoints = new Endpoints(this);
|
|
60
61
|
this.schedules = new Schedules(this);
|
|
62
|
+
this.queues = new MessageQueues(this);
|
|
61
63
|
}
|
|
62
64
|
/**
|
|
63
65
|
* Send a request immediately with reliable delivery and retries.
|
|
@@ -142,7 +144,7 @@ var Runlater = class {
|
|
|
142
144
|
body: options.body != null ? JSON.stringify(options.body) : void 0,
|
|
143
145
|
timeout_ms: options.timeout,
|
|
144
146
|
retry_attempts: options.retries,
|
|
145
|
-
|
|
147
|
+
lane: options.lane,
|
|
146
148
|
callback_url: options.callback,
|
|
147
149
|
enabled: options.enabled,
|
|
148
150
|
script: options.script
|
|
@@ -175,7 +177,7 @@ var Runlater = class {
|
|
|
175
177
|
body: t.body != null ? JSON.stringify(t.body) : void 0,
|
|
176
178
|
timeout_ms: t.timeout,
|
|
177
179
|
retry_attempts: t.retries,
|
|
178
|
-
|
|
180
|
+
lane: t.lane,
|
|
179
181
|
callback_url: t.callback,
|
|
180
182
|
enabled: t.enabled,
|
|
181
183
|
script: t.script
|
|
@@ -210,7 +212,7 @@ var Runlater = class {
|
|
|
210
212
|
body: options.body != null ? JSON.stringify(options.body) : void 0,
|
|
211
213
|
timeout_ms: options.timeout,
|
|
212
214
|
retry_attempts: options.retries,
|
|
213
|
-
|
|
215
|
+
lane: options.lane,
|
|
214
216
|
callback_url: options.callback,
|
|
215
217
|
script: options.script,
|
|
216
218
|
debounce: options.debounce != null ? formatDelay(options.debounce) : void 0,
|
|
@@ -222,7 +224,7 @@ var Runlater = class {
|
|
|
222
224
|
const headers = {
|
|
223
225
|
Authorization: `Bearer ${this.apiKey}`,
|
|
224
226
|
"Content-Type": "application/json",
|
|
225
|
-
"User-Agent": "runlater-js/0.
|
|
227
|
+
"User-Agent": "runlater-js/0.12.0"
|
|
226
228
|
};
|
|
227
229
|
if (options.idempotencyKey) {
|
|
228
230
|
headers["Idempotency-Key"] = options.idempotencyKey;
|
|
@@ -253,7 +255,7 @@ var Tasks = class {
|
|
|
253
255
|
}
|
|
254
256
|
async list(options = {}) {
|
|
255
257
|
const params = new URLSearchParams();
|
|
256
|
-
if (options.
|
|
258
|
+
if (options.lane != null) params.set("lane", options.lane);
|
|
257
259
|
if (options.limit != null) params.set("limit", String(options.limit));
|
|
258
260
|
if (options.offset != null) params.set("offset", String(options.offset));
|
|
259
261
|
const query = params.toString();
|
|
@@ -291,11 +293,11 @@ var Tasks = class {
|
|
|
291
293
|
* optionally override method, headers, body, and name. Top-level
|
|
292
294
|
* settings serve as defaults.
|
|
293
295
|
*
|
|
294
|
-
* Use the
|
|
296
|
+
* Use the lane name with `cancelLane()` to cancel them as a group.
|
|
295
297
|
*
|
|
296
298
|
* ```js
|
|
297
299
|
* await rl.tasks.batch({
|
|
298
|
-
*
|
|
300
|
+
* lane: "march-newsletter",
|
|
299
301
|
* method: "POST",
|
|
300
302
|
* run_at: "2026-03-01T09:00:00Z",
|
|
301
303
|
* tasks: [
|
|
@@ -307,7 +309,7 @@ var Tasks = class {
|
|
|
307
309
|
*/
|
|
308
310
|
async batch(options) {
|
|
309
311
|
const body = {
|
|
310
|
-
|
|
312
|
+
lane: options.lane,
|
|
311
313
|
tasks: options.tasks.map((t) => ({
|
|
312
314
|
url: t.url,
|
|
313
315
|
method: t.method,
|
|
@@ -333,19 +335,19 @@ var Tasks = class {
|
|
|
333
335
|
return res.data;
|
|
334
336
|
}
|
|
335
337
|
/**
|
|
336
|
-
* Cancel all tasks in a
|
|
338
|
+
* Cancel all tasks in a lane.
|
|
337
339
|
*
|
|
338
|
-
* Soft-deletes every task in the
|
|
340
|
+
* Soft-deletes every task in the lane and removes their pending executions.
|
|
339
341
|
*
|
|
340
342
|
* ```js
|
|
341
|
-
* const { cancelled } = await rl.tasks.
|
|
343
|
+
* const { cancelled } = await rl.tasks.cancelLane("march-newsletter")
|
|
342
344
|
* console.log(`Cancelled ${cancelled} tasks`)
|
|
343
345
|
* ```
|
|
344
346
|
*/
|
|
345
|
-
async
|
|
347
|
+
async cancelLane(lane) {
|
|
346
348
|
const res = await this.client.request(
|
|
347
349
|
"DELETE",
|
|
348
|
-
`/tasks?
|
|
350
|
+
`/tasks?lane=${encodeURIComponent(lane)}`
|
|
349
351
|
);
|
|
350
352
|
return res.data;
|
|
351
353
|
}
|
|
@@ -504,6 +506,135 @@ var Endpoints = class {
|
|
|
504
506
|
return res.data;
|
|
505
507
|
}
|
|
506
508
|
};
|
|
509
|
+
var MessageQueues = class {
|
|
510
|
+
constructor(client) {
|
|
511
|
+
this.client = client;
|
|
512
|
+
}
|
|
513
|
+
/** List all message queues. */
|
|
514
|
+
async list() {
|
|
515
|
+
const res = await this.client.request("GET", "/mq");
|
|
516
|
+
return res.data;
|
|
517
|
+
}
|
|
518
|
+
/** Create a new message queue. */
|
|
519
|
+
async create(options) {
|
|
520
|
+
const res = await this.client.request("POST", "/mq", {
|
|
521
|
+
body: options
|
|
522
|
+
});
|
|
523
|
+
return res.data;
|
|
524
|
+
}
|
|
525
|
+
/** Get a message queue by slug. */
|
|
526
|
+
async get(slug) {
|
|
527
|
+
const res = await this.client.request("GET", `/mq/${slug}`);
|
|
528
|
+
return res.data;
|
|
529
|
+
}
|
|
530
|
+
/** Update a message queue. */
|
|
531
|
+
async update(slug, options) {
|
|
532
|
+
const res = await this.client.request("PATCH", `/mq/${slug}`, {
|
|
533
|
+
body: options
|
|
534
|
+
});
|
|
535
|
+
return res.data;
|
|
536
|
+
}
|
|
537
|
+
/** Delete a message queue. */
|
|
538
|
+
async delete(slug) {
|
|
539
|
+
await this.client.request("DELETE", `/mq/${slug}`);
|
|
540
|
+
}
|
|
541
|
+
/** Get queue statistics. */
|
|
542
|
+
async stats(slug) {
|
|
543
|
+
const res = await this.client.request("GET", `/mq/${slug}/stats`);
|
|
544
|
+
return res.data;
|
|
545
|
+
}
|
|
546
|
+
/** Enqueue a single message. Optionally delay or schedule for a future time. */
|
|
547
|
+
async enqueue(slug, body, options) {
|
|
548
|
+
const payload = { body };
|
|
549
|
+
if (options?.delay != null) payload.delay = formatDelay(options.delay);
|
|
550
|
+
if (options?.run_at != null) payload.run_at = options.run_at;
|
|
551
|
+
const res = await this.client.request("POST", `/mq/${slug}/messages`, {
|
|
552
|
+
body: payload
|
|
553
|
+
});
|
|
554
|
+
return res.data;
|
|
555
|
+
}
|
|
556
|
+
/** Enqueue multiple messages at once. Each message can have its own delay/run_at. */
|
|
557
|
+
async enqueueBatch(slug, messages) {
|
|
558
|
+
const formatted = messages.map((m) => {
|
|
559
|
+
const msg = { body: m.body };
|
|
560
|
+
if (m.delay != null) msg.delay = formatDelay(m.delay);
|
|
561
|
+
if (m.run_at != null) msg.run_at = m.run_at;
|
|
562
|
+
return msg;
|
|
563
|
+
});
|
|
564
|
+
const res = await this.client.request(
|
|
565
|
+
"POST",
|
|
566
|
+
`/mq/${slug}/messages/batch`,
|
|
567
|
+
{ body: { messages: formatted } }
|
|
568
|
+
);
|
|
569
|
+
return res.data;
|
|
570
|
+
}
|
|
571
|
+
/** Receive messages from the queue. */
|
|
572
|
+
async receive(slug, options = {}) {
|
|
573
|
+
const params = new URLSearchParams();
|
|
574
|
+
if (options.max != null) params.set("max", String(options.max));
|
|
575
|
+
if (options.wait != null) params.set("wait", String(options.wait));
|
|
576
|
+
const query = params.toString();
|
|
577
|
+
const res = await this.client.request(
|
|
578
|
+
"GET",
|
|
579
|
+
`/mq/${slug}/receive${query ? `?${query}` : ""}`
|
|
580
|
+
);
|
|
581
|
+
return res.data;
|
|
582
|
+
}
|
|
583
|
+
/** Acknowledge (complete) a message by receipt handle. */
|
|
584
|
+
async ack(slug, receiptHandle) {
|
|
585
|
+
await this.client.request("DELETE", `/mq/${slug}/ack/${receiptHandle}`);
|
|
586
|
+
}
|
|
587
|
+
/** Nack (release) a message back to the queue. */
|
|
588
|
+
async nack(slug, receiptHandle) {
|
|
589
|
+
await this.client.request("POST", `/mq/${slug}/nack/${receiptHandle}`);
|
|
590
|
+
}
|
|
591
|
+
/** Acknowledge multiple messages at once. */
|
|
592
|
+
async ackBatch(slug, receiptHandles) {
|
|
593
|
+
const res = await this.client.request(
|
|
594
|
+
"POST",
|
|
595
|
+
`/mq/${slug}/ack/batch`,
|
|
596
|
+
{ body: { receipt_handles: receiptHandles } }
|
|
597
|
+
);
|
|
598
|
+
return res.data;
|
|
599
|
+
}
|
|
600
|
+
/** List messages in the queue with optional filtering. */
|
|
601
|
+
async messages(slug, options = {}) {
|
|
602
|
+
const params = new URLSearchParams();
|
|
603
|
+
if (options.status != null) params.set("status", options.status);
|
|
604
|
+
if (options.limit != null) params.set("limit", String(options.limit));
|
|
605
|
+
if (options.offset != null) params.set("offset", String(options.offset));
|
|
606
|
+
const query = params.toString();
|
|
607
|
+
const res = await this.client.request(
|
|
608
|
+
"GET",
|
|
609
|
+
`/mq/${slug}/messages${query ? `?${query}` : ""}`
|
|
610
|
+
);
|
|
611
|
+
return res.data;
|
|
612
|
+
}
|
|
613
|
+
/** Get a specific message by ID. */
|
|
614
|
+
async getMessage(slug, id) {
|
|
615
|
+
const res = await this.client.request(
|
|
616
|
+
"GET",
|
|
617
|
+
`/mq/${slug}/messages/${id}`
|
|
618
|
+
);
|
|
619
|
+
return res.data;
|
|
620
|
+
}
|
|
621
|
+
/** Pause the queue. */
|
|
622
|
+
async pause(slug) {
|
|
623
|
+
const res = await this.client.request(
|
|
624
|
+
"POST",
|
|
625
|
+
`/mq/${slug}/pause`
|
|
626
|
+
);
|
|
627
|
+
return res.data;
|
|
628
|
+
}
|
|
629
|
+
/** Resume a paused queue. */
|
|
630
|
+
async resume(slug) {
|
|
631
|
+
const res = await this.client.request(
|
|
632
|
+
"POST",
|
|
633
|
+
`/mq/${slug}/resume`
|
|
634
|
+
);
|
|
635
|
+
return res.data;
|
|
636
|
+
}
|
|
637
|
+
};
|
|
507
638
|
function formatDelay(delay) {
|
|
508
639
|
if (typeof delay === "number") return `${delay}s`;
|
|
509
640
|
return delay;
|
package/dist/index.mjs
CHANGED
|
@@ -19,6 +19,7 @@ var Runlater = class {
|
|
|
19
19
|
monitors;
|
|
20
20
|
endpoints;
|
|
21
21
|
schedules;
|
|
22
|
+
queues;
|
|
22
23
|
constructor(options) {
|
|
23
24
|
if (typeof options === "string") {
|
|
24
25
|
this.apiKey = options;
|
|
@@ -31,6 +32,7 @@ var Runlater = class {
|
|
|
31
32
|
this.monitors = new Monitors(this);
|
|
32
33
|
this.endpoints = new Endpoints(this);
|
|
33
34
|
this.schedules = new Schedules(this);
|
|
35
|
+
this.queues = new MessageQueues(this);
|
|
34
36
|
}
|
|
35
37
|
/**
|
|
36
38
|
* Send a request immediately with reliable delivery and retries.
|
|
@@ -115,7 +117,7 @@ var Runlater = class {
|
|
|
115
117
|
body: options.body != null ? JSON.stringify(options.body) : void 0,
|
|
116
118
|
timeout_ms: options.timeout,
|
|
117
119
|
retry_attempts: options.retries,
|
|
118
|
-
|
|
120
|
+
lane: options.lane,
|
|
119
121
|
callback_url: options.callback,
|
|
120
122
|
enabled: options.enabled,
|
|
121
123
|
script: options.script
|
|
@@ -148,7 +150,7 @@ var Runlater = class {
|
|
|
148
150
|
body: t.body != null ? JSON.stringify(t.body) : void 0,
|
|
149
151
|
timeout_ms: t.timeout,
|
|
150
152
|
retry_attempts: t.retries,
|
|
151
|
-
|
|
153
|
+
lane: t.lane,
|
|
152
154
|
callback_url: t.callback,
|
|
153
155
|
enabled: t.enabled,
|
|
154
156
|
script: t.script
|
|
@@ -183,7 +185,7 @@ var Runlater = class {
|
|
|
183
185
|
body: options.body != null ? JSON.stringify(options.body) : void 0,
|
|
184
186
|
timeout_ms: options.timeout,
|
|
185
187
|
retry_attempts: options.retries,
|
|
186
|
-
|
|
188
|
+
lane: options.lane,
|
|
187
189
|
callback_url: options.callback,
|
|
188
190
|
script: options.script,
|
|
189
191
|
debounce: options.debounce != null ? formatDelay(options.debounce) : void 0,
|
|
@@ -195,7 +197,7 @@ var Runlater = class {
|
|
|
195
197
|
const headers = {
|
|
196
198
|
Authorization: `Bearer ${this.apiKey}`,
|
|
197
199
|
"Content-Type": "application/json",
|
|
198
|
-
"User-Agent": "runlater-js/0.
|
|
200
|
+
"User-Agent": "runlater-js/0.12.0"
|
|
199
201
|
};
|
|
200
202
|
if (options.idempotencyKey) {
|
|
201
203
|
headers["Idempotency-Key"] = options.idempotencyKey;
|
|
@@ -226,7 +228,7 @@ var Tasks = class {
|
|
|
226
228
|
}
|
|
227
229
|
async list(options = {}) {
|
|
228
230
|
const params = new URLSearchParams();
|
|
229
|
-
if (options.
|
|
231
|
+
if (options.lane != null) params.set("lane", options.lane);
|
|
230
232
|
if (options.limit != null) params.set("limit", String(options.limit));
|
|
231
233
|
if (options.offset != null) params.set("offset", String(options.offset));
|
|
232
234
|
const query = params.toString();
|
|
@@ -264,11 +266,11 @@ var Tasks = class {
|
|
|
264
266
|
* optionally override method, headers, body, and name. Top-level
|
|
265
267
|
* settings serve as defaults.
|
|
266
268
|
*
|
|
267
|
-
* Use the
|
|
269
|
+
* Use the lane name with `cancelLane()` to cancel them as a group.
|
|
268
270
|
*
|
|
269
271
|
* ```js
|
|
270
272
|
* await rl.tasks.batch({
|
|
271
|
-
*
|
|
273
|
+
* lane: "march-newsletter",
|
|
272
274
|
* method: "POST",
|
|
273
275
|
* run_at: "2026-03-01T09:00:00Z",
|
|
274
276
|
* tasks: [
|
|
@@ -280,7 +282,7 @@ var Tasks = class {
|
|
|
280
282
|
*/
|
|
281
283
|
async batch(options) {
|
|
282
284
|
const body = {
|
|
283
|
-
|
|
285
|
+
lane: options.lane,
|
|
284
286
|
tasks: options.tasks.map((t) => ({
|
|
285
287
|
url: t.url,
|
|
286
288
|
method: t.method,
|
|
@@ -306,19 +308,19 @@ var Tasks = class {
|
|
|
306
308
|
return res.data;
|
|
307
309
|
}
|
|
308
310
|
/**
|
|
309
|
-
* Cancel all tasks in a
|
|
311
|
+
* Cancel all tasks in a lane.
|
|
310
312
|
*
|
|
311
|
-
* Soft-deletes every task in the
|
|
313
|
+
* Soft-deletes every task in the lane and removes their pending executions.
|
|
312
314
|
*
|
|
313
315
|
* ```js
|
|
314
|
-
* const { cancelled } = await rl.tasks.
|
|
316
|
+
* const { cancelled } = await rl.tasks.cancelLane("march-newsletter")
|
|
315
317
|
* console.log(`Cancelled ${cancelled} tasks`)
|
|
316
318
|
* ```
|
|
317
319
|
*/
|
|
318
|
-
async
|
|
320
|
+
async cancelLane(lane) {
|
|
319
321
|
const res = await this.client.request(
|
|
320
322
|
"DELETE",
|
|
321
|
-
`/tasks?
|
|
323
|
+
`/tasks?lane=${encodeURIComponent(lane)}`
|
|
322
324
|
);
|
|
323
325
|
return res.data;
|
|
324
326
|
}
|
|
@@ -477,6 +479,135 @@ var Endpoints = class {
|
|
|
477
479
|
return res.data;
|
|
478
480
|
}
|
|
479
481
|
};
|
|
482
|
+
var MessageQueues = class {
|
|
483
|
+
constructor(client) {
|
|
484
|
+
this.client = client;
|
|
485
|
+
}
|
|
486
|
+
/** List all message queues. */
|
|
487
|
+
async list() {
|
|
488
|
+
const res = await this.client.request("GET", "/mq");
|
|
489
|
+
return res.data;
|
|
490
|
+
}
|
|
491
|
+
/** Create a new message queue. */
|
|
492
|
+
async create(options) {
|
|
493
|
+
const res = await this.client.request("POST", "/mq", {
|
|
494
|
+
body: options
|
|
495
|
+
});
|
|
496
|
+
return res.data;
|
|
497
|
+
}
|
|
498
|
+
/** Get a message queue by slug. */
|
|
499
|
+
async get(slug) {
|
|
500
|
+
const res = await this.client.request("GET", `/mq/${slug}`);
|
|
501
|
+
return res.data;
|
|
502
|
+
}
|
|
503
|
+
/** Update a message queue. */
|
|
504
|
+
async update(slug, options) {
|
|
505
|
+
const res = await this.client.request("PATCH", `/mq/${slug}`, {
|
|
506
|
+
body: options
|
|
507
|
+
});
|
|
508
|
+
return res.data;
|
|
509
|
+
}
|
|
510
|
+
/** Delete a message queue. */
|
|
511
|
+
async delete(slug) {
|
|
512
|
+
await this.client.request("DELETE", `/mq/${slug}`);
|
|
513
|
+
}
|
|
514
|
+
/** Get queue statistics. */
|
|
515
|
+
async stats(slug) {
|
|
516
|
+
const res = await this.client.request("GET", `/mq/${slug}/stats`);
|
|
517
|
+
return res.data;
|
|
518
|
+
}
|
|
519
|
+
/** Enqueue a single message. Optionally delay or schedule for a future time. */
|
|
520
|
+
async enqueue(slug, body, options) {
|
|
521
|
+
const payload = { body };
|
|
522
|
+
if (options?.delay != null) payload.delay = formatDelay(options.delay);
|
|
523
|
+
if (options?.run_at != null) payload.run_at = options.run_at;
|
|
524
|
+
const res = await this.client.request("POST", `/mq/${slug}/messages`, {
|
|
525
|
+
body: payload
|
|
526
|
+
});
|
|
527
|
+
return res.data;
|
|
528
|
+
}
|
|
529
|
+
/** Enqueue multiple messages at once. Each message can have its own delay/run_at. */
|
|
530
|
+
async enqueueBatch(slug, messages) {
|
|
531
|
+
const formatted = messages.map((m) => {
|
|
532
|
+
const msg = { body: m.body };
|
|
533
|
+
if (m.delay != null) msg.delay = formatDelay(m.delay);
|
|
534
|
+
if (m.run_at != null) msg.run_at = m.run_at;
|
|
535
|
+
return msg;
|
|
536
|
+
});
|
|
537
|
+
const res = await this.client.request(
|
|
538
|
+
"POST",
|
|
539
|
+
`/mq/${slug}/messages/batch`,
|
|
540
|
+
{ body: { messages: formatted } }
|
|
541
|
+
);
|
|
542
|
+
return res.data;
|
|
543
|
+
}
|
|
544
|
+
/** Receive messages from the queue. */
|
|
545
|
+
async receive(slug, options = {}) {
|
|
546
|
+
const params = new URLSearchParams();
|
|
547
|
+
if (options.max != null) params.set("max", String(options.max));
|
|
548
|
+
if (options.wait != null) params.set("wait", String(options.wait));
|
|
549
|
+
const query = params.toString();
|
|
550
|
+
const res = await this.client.request(
|
|
551
|
+
"GET",
|
|
552
|
+
`/mq/${slug}/receive${query ? `?${query}` : ""}`
|
|
553
|
+
);
|
|
554
|
+
return res.data;
|
|
555
|
+
}
|
|
556
|
+
/** Acknowledge (complete) a message by receipt handle. */
|
|
557
|
+
async ack(slug, receiptHandle) {
|
|
558
|
+
await this.client.request("DELETE", `/mq/${slug}/ack/${receiptHandle}`);
|
|
559
|
+
}
|
|
560
|
+
/** Nack (release) a message back to the queue. */
|
|
561
|
+
async nack(slug, receiptHandle) {
|
|
562
|
+
await this.client.request("POST", `/mq/${slug}/nack/${receiptHandle}`);
|
|
563
|
+
}
|
|
564
|
+
/** Acknowledge multiple messages at once. */
|
|
565
|
+
async ackBatch(slug, receiptHandles) {
|
|
566
|
+
const res = await this.client.request(
|
|
567
|
+
"POST",
|
|
568
|
+
`/mq/${slug}/ack/batch`,
|
|
569
|
+
{ body: { receipt_handles: receiptHandles } }
|
|
570
|
+
);
|
|
571
|
+
return res.data;
|
|
572
|
+
}
|
|
573
|
+
/** List messages in the queue with optional filtering. */
|
|
574
|
+
async messages(slug, options = {}) {
|
|
575
|
+
const params = new URLSearchParams();
|
|
576
|
+
if (options.status != null) params.set("status", options.status);
|
|
577
|
+
if (options.limit != null) params.set("limit", String(options.limit));
|
|
578
|
+
if (options.offset != null) params.set("offset", String(options.offset));
|
|
579
|
+
const query = params.toString();
|
|
580
|
+
const res = await this.client.request(
|
|
581
|
+
"GET",
|
|
582
|
+
`/mq/${slug}/messages${query ? `?${query}` : ""}`
|
|
583
|
+
);
|
|
584
|
+
return res.data;
|
|
585
|
+
}
|
|
586
|
+
/** Get a specific message by ID. */
|
|
587
|
+
async getMessage(slug, id) {
|
|
588
|
+
const res = await this.client.request(
|
|
589
|
+
"GET",
|
|
590
|
+
`/mq/${slug}/messages/${id}`
|
|
591
|
+
);
|
|
592
|
+
return res.data;
|
|
593
|
+
}
|
|
594
|
+
/** Pause the queue. */
|
|
595
|
+
async pause(slug) {
|
|
596
|
+
const res = await this.client.request(
|
|
597
|
+
"POST",
|
|
598
|
+
`/mq/${slug}/pause`
|
|
599
|
+
);
|
|
600
|
+
return res.data;
|
|
601
|
+
}
|
|
602
|
+
/** Resume a paused queue. */
|
|
603
|
+
async resume(slug) {
|
|
604
|
+
const res = await this.client.request(
|
|
605
|
+
"POST",
|
|
606
|
+
`/mq/${slug}/resume`
|
|
607
|
+
);
|
|
608
|
+
return res.data;
|
|
609
|
+
}
|
|
610
|
+
};
|
|
480
611
|
function formatDelay(delay) {
|
|
481
612
|
if (typeof delay === "number") return `${delay}s`;
|
|
482
613
|
return delay;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "runlater-js",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Delayed tasks, cron jobs, and reliable webhooks. No infrastructure required.",
|
|
3
|
+
"version": "0.13.0",
|
|
4
|
+
"description": "Delayed tasks, cron jobs, message queues, and reliable webhooks. No infrastructure required.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
7
7
|
"types": "./dist/index.d.ts",
|