@warlock.js/notifications 5.12.0 → 5.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/CHANGELOG.md +6 -0
- package/llms-full.txt +57 -36
- package/llms.txt +1 -1
- package/package.json +6 -6
- package/skills/queue-notifications/SKILL.md +57 -36
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to `@warlock.js/notifications` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
|
|
6
6
|
|
|
7
|
+
## 5.13.0 - 2026-09-17
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Restored the portable `typecheck` script after Core's path-alias resolver was made safe for an absent first target.
|
|
12
|
+
|
|
7
13
|
## 5.11.0 - 2026-09-14
|
|
8
14
|
|
|
9
15
|
_Released in lockstep with the `@warlock.js/*` family; no package-specific changes in 5.11.0._
|
package/llms-full.txt
CHANGED
|
@@ -570,85 +570,106 @@ A handler that throws is logged and swallowed — the other handlers for the sam
|
|
|
570
570
|
|
|
571
571
|
---
|
|
572
572
|
name: queue-notifications
|
|
573
|
-
description:
|
|
573
|
+
description: "Send notifications asynchronously through the herald backend or the BullMQ adapter. Configure a QueueDispatcher in config/notifications.ts, then use notif.queue(to, data, options?) to enqueue rendered jobs. Herald uses heraldQueue() and startNotificationsWorker(); queueNotificationDispatcher() from @warlock.js/queue/notifications uses BullMQ, supports retries, and honours SendOptions.delay. Without a queue configured, .queue() rejects NoQueueDispatcherError. Triggers: heraldQueue, startNotificationsWorker, queueNotificationDispatcher, QueueDispatcher, .queue(, async notifications, queue notifications, notification worker, background notifications, notifications.dispatch. Skip: synchronous sends - @warlock.js/notifications/define-notification/SKILL.md; herald itself - @warlock.js/herald/*."
|
|
574
574
|
---
|
|
575
575
|
|
|
576
576
|
# Queue notifications (async)
|
|
577
577
|
|
|
578
|
-
Move slow channels (SMTP, HTTP) off the request path. `.queue()`
|
|
579
|
-
|
|
578
|
+
Move slow channels (SMTP, HTTP) off the request path. `.queue()` renders the
|
|
579
|
+
payload and resolves the route before passing a serializable job to a dispatcher.
|
|
580
580
|
|
|
581
|
-
## Wire the dispatcher
|
|
581
|
+
## Wire the herald dispatcher
|
|
582
582
|
|
|
583
583
|
```ts title="src/config/notifications.ts"
|
|
584
|
-
import {
|
|
584
|
+
import {
|
|
585
|
+
type NotificationConfig,
|
|
586
|
+
heraldQueue,
|
|
587
|
+
inApp,
|
|
588
|
+
mailChannel,
|
|
589
|
+
} from "@warlock.js/notifications";
|
|
585
590
|
import { Notification } from "app/notifications/notification.model";
|
|
586
591
|
|
|
587
592
|
const config: NotificationConfig = {
|
|
588
593
|
channels: { mail: mailChannel(), database: inApp.configure({ model: Notification }) },
|
|
589
|
-
queue: heraldQueue(),
|
|
594
|
+
queue: heraldQueue(),
|
|
590
595
|
};
|
|
591
596
|
|
|
592
|
-
export default config;
|
|
597
|
+
export default config;
|
|
593
598
|
```
|
|
594
599
|
|
|
595
|
-
`heraldQueue({ channel?, broker? })` publishes to `"notifications.dispatch"`
|
|
596
|
-
the default broker unless overridden. It lazy-imports `@warlock.js/herald`;
|
|
597
|
-
that package
|
|
600
|
+
`heraldQueue({ channel?, broker? })` publishes to `"notifications.dispatch"`
|
|
601
|
+
on the default broker unless overridden. It lazy-imports `@warlock.js/herald`;
|
|
602
|
+
if that package is missing, the first `.queue()` throws an install message.
|
|
603
|
+
|
|
604
|
+
## Use BullMQ for delayed or retried delivery
|
|
605
|
+
|
|
606
|
+
With `@warlock.js/queue` configured, use its notification dispatcher instead
|
|
607
|
+
of the herald dispatcher:
|
|
608
|
+
|
|
609
|
+
```ts title="src/config/notifications.ts"
|
|
610
|
+
import { type NotificationConfig, mailChannel } from "@warlock.js/notifications";
|
|
611
|
+
import { queueNotificationDispatcher } from "@warlock.js/queue/notifications";
|
|
612
|
+
|
|
613
|
+
const config: NotificationConfig = {
|
|
614
|
+
channels: { mail: mailChannel() },
|
|
615
|
+
queue: queueNotificationDispatcher({ attempts: 3 }),
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
export default config;
|
|
619
|
+
```
|
|
598
620
|
|
|
599
|
-
|
|
600
|
-
|
|
621
|
+
The BullMQ adapter honours `SendOptions.delay`: numeric delays are seconds and
|
|
622
|
+
string delays use the normal duration syntax, such as `"10m"`. It also supports
|
|
623
|
+
BullMQ retries through `attempts` and `backoff`.
|
|
601
624
|
|
|
602
|
-
## Run the worker
|
|
625
|
+
## Run the herald worker
|
|
603
626
|
|
|
604
|
-
In a worker entrypoint (or the web process), after the config
|
|
605
|
-
|
|
627
|
+
In a worker entrypoint (or the web process), after the config and herald broker
|
|
628
|
+
are up:
|
|
606
629
|
|
|
607
630
|
```ts
|
|
608
631
|
import { startNotificationsWorker } from "@warlock.js/notifications";
|
|
609
632
|
|
|
610
|
-
await startNotificationsWorker();
|
|
633
|
+
await startNotificationsWorker();
|
|
611
634
|
```
|
|
612
635
|
|
|
613
|
-
The worker
|
|
614
|
-
`channel.send({ payload, route, options })`. The
|
|
615
|
-
|
|
616
|
-
worker needs no recipient model.
|
|
636
|
+
The worker looks up the channel by name and runs
|
|
637
|
+
`channel.send({ payload, route, options })`. The worker needs no recipient model
|
|
638
|
+
because rendering happened at enqueue time.
|
|
617
639
|
|
|
618
640
|
## Send
|
|
619
641
|
|
|
620
642
|
```ts
|
|
621
|
-
await orderShipped.queue(user, { order });
|
|
643
|
+
await orderShipped.queue(user, { order });
|
|
622
644
|
await orderShipped.queue(buyers, { order }, { delay: "10m" });
|
|
623
|
-
await notify.mail(user, payload, {
|
|
645
|
+
await notify.mail(user, payload, {/* synchronous - notify.* does not queue */});
|
|
624
646
|
```
|
|
625
647
|
|
|
626
|
-
`.queue()` renders
|
|
627
|
-
|
|
648
|
+
`.queue()` renders per recipient and enqueues one job per recipient. Without a
|
|
649
|
+
configured dispatcher, it rejects `NoQueueDispatcherError`.
|
|
628
650
|
|
|
629
651
|
## Idempotency
|
|
630
652
|
|
|
631
|
-
Pass `idempotencyKey` so a redelivered
|
|
632
|
-
in-app row
|
|
653
|
+
Pass `idempotencyKey` so a redelivered or retried job does not create a duplicate
|
|
654
|
+
in-app row. `createFor` finds or creates the row by that key.
|
|
633
655
|
|
|
634
656
|
```ts
|
|
635
657
|
await orderShipped.queue(user, { order }, { idempotencyKey: `ship:${order.id}` });
|
|
636
658
|
```
|
|
637
659
|
|
|
638
|
-
##
|
|
660
|
+
## Current limits
|
|
639
661
|
|
|
640
|
-
-
|
|
641
|
-
immediately.
|
|
642
|
-
-
|
|
643
|
-
|
|
644
|
-
- Rate-limit budget is consumed at
|
|
645
|
-
`RateLimiter` docstring).
|
|
662
|
+
- With the herald backend, `delay` is carried on the job but not honoured; the
|
|
663
|
+
worker delivers immediately. Use the BullMQ adapter for delayed delivery.
|
|
664
|
+
- Herald has no retry or dead-letter handling yet; failed `channel.send` calls
|
|
665
|
+
are logged and acknowledged.
|
|
666
|
+
- Rate-limit budget is consumed at enqueue time for queued sends.
|
|
646
667
|
|
|
647
668
|
## See also
|
|
648
669
|
|
|
649
|
-
- [`define-notification/SKILL.md`](../define-notification/SKILL.md)
|
|
650
|
-
- [`configure-notifications/SKILL.md`](../configure-notifications/SKILL.md)
|
|
651
|
-
- [`@warlock.js/herald/herald-basics/SKILL.md`](../../../herald/skills/herald-basics/SKILL.md)
|
|
670
|
+
- [`define-notification/SKILL.md`](../define-notification/SKILL.md) - `.queue()` on a defined notification.
|
|
671
|
+
- [`configure-notifications/SKILL.md`](../configure-notifications/SKILL.md) - the `queue` config slot.
|
|
672
|
+
- [`@warlock.js/herald/herald-basics/SKILL.md`](../../../herald/skills/herald-basics/SKILL.md) - connecting the broker.
|
|
652
673
|
|
|
653
674
|
|
|
654
675
|
## send-ad-hoc `@warlock.js/notifications/send-ad-hoc/SKILL.md`
|
package/llms.txt
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
- [define-notification](@warlock.js/notifications/define-notification/SKILL.md): Build a reusable multi-channel notification with `defineNotification<Data>({ type, via, ...renderers })`. `type` is the stable identifier preference/rate-limit gates use AND defaults the database channel's `type`. `via` is `ChannelName[]` OR `(data, to) => ChannelName[]` for per-recipient channel selection. Renderers are `(data, to, ctx) => NotificationChannels[C]`; `ctx` carries `locale` + `meta` from `SendOptions`. The returned object exposes `.send(to|to[], data, options?)`, `.queue(to|to[], data, options?)`, and `.only(...channels)`. Per-recipient + per-channel `Promise.allSettled` isolates failures; the database channel's `type` is auto-defaulted from `def.type`; `SendOptions.idempotencyKey` is injected into the database payload. Triggers: `defineNotification`, `via`, "reusable notification", "multi-channel notification", "send through several channels at once", "render per channel", `RenderContext`, `def.type`; "force on a notification", "queue with delay"; typical import `import { defineNotification } from "@warlock.js/notifications"`. Skip: single-channel ad-hoc sends — `@warlock.js/notifications/send-ad-hoc/SKILL.md`; adding a brand-new channel — `@warlock.js/notifications/define-channel/SKILL.md`; observing dispatch outcomes — `@warlock.js/notifications/observe-notifications/SKILL.md`.
|
|
12
12
|
- [notifications-basics](@warlock.js/notifications/notifications-basics/SKILL.md): Front-door for `@warlock.js/notifications` — what the package is, when to reach for it, and the four moving parts (channel registry, defineNotification, notify, inApp). Multi-channel dispatch: define once, fire anywhere. Recipients are cascade `Model` instances; payloads are typed per channel via a declaration-merge `NotificationChannels` registry; reusable definitions go through `defineNotification`; ad-hoc per-channel sends go through the `notify.<channel>` proxy; the in-app database channel is read via the `inApp` facade. Phase 1 ships `mail` + `database`; bridges-backed channels (whatsapp/telegram/push/slack) arrive in Phase 2. Triggers: `defineNotification`, `notify.<channel>`, `inApp.configure`, `setNotificationConfig`, `NotificationConfig`, `NotificationChannels`; "send a notification", "in-app notifications", "what channels can I use", "what is `@warlock.js/notifications`", "where do I start"; typical import `import { defineNotification, notify, inApp } from "@warlock.js/notifications"`. Skip: configuring channels in `config/notifications.ts` — `@warlock.js/notifications/configure-notifications/SKILL.md`; building a multi-channel definition — `@warlock.js/notifications/define-notification/SKILL.md`; reading in-app rows — `@warlock.js/notifications/use-in-app/SKILL.md`.
|
|
13
13
|
- [observe-notifications](@warlock.js/notifications/observe-notifications/SKILL.md): Wire metrics, logging, tracing, and audits via `notifications.on(event, handler)` — four events fire per (channel, recipient): `sending` (gates passed, about to hit the transport), `sent` (succeeded), `failed` (channel threw — carries the Error), `skipped` (a pre-send gate dropped it — carries `reason: "preference" | "rate-limit"`). Every event carries the recipient as `notifiable?` (undefined only for raw-target ad-hoc sends) and a `dispatchId` — `sending` and its terminal `sent`/`failed` share it, so observers can pair them (spans, latency, hung-send detection). `sent`/`failed` also carry `durationMs`. Handler exceptions are logged-and-swallowed so one bad listener can not break the dispatcher. `on(...)` returns an unsubscribe function; `off(event, handler)` exists for symmetry. Triggers: `notifications.on`, `notifications.off`, `"sending"` event, `"sent"` event, `"failed"` event, `"skipped"` event, `dispatchId`, `durationMs`, `NotificationEvents`, "notification metrics", "notification latency", "trace notifications", "notification audit log", "track notification drops"; typical import `import { notifications } from "@warlock.js/notifications"`. Skip: building notifications — `@warlock.js/notifications/define-notification/SKILL.md`; configuring the preference/rate-limit gates that produce `skipped` — `@warlock.js/notifications/configure-notifications/SKILL.md`.
|
|
14
|
-
- [queue-notifications](@warlock.js/notifications/queue-notifications/SKILL.md): Send notifications asynchronously
|
|
14
|
+
- [queue-notifications](@warlock.js/notifications/queue-notifications/SKILL.md): Send notifications asynchronously through the herald backend or the BullMQ adapter. Configure a QueueDispatcher in config/notifications.ts, then use notif.queue(to, data, options?) to enqueue rendered jobs. Herald uses heraldQueue() and startNotificationsWorker(); queueNotificationDispatcher() from @warlock.js/queue/notifications uses BullMQ, supports retries, and honours SendOptions.delay. Without a queue configured, .queue() rejects NoQueueDispatcherError. Triggers: heraldQueue, startNotificationsWorker, queueNotificationDispatcher, QueueDispatcher, .queue(, async notifications, queue notifications, notification worker, background notifications, notifications.dispatch. Skip: synchronous sends - @warlock.js/notifications/define-notification/SKILL.md; herald itself - @warlock.js/herald/*.
|
|
15
15
|
- [send-ad-hoc](@warlock.js/notifications/send-ad-hoc/SKILL.md): Ad-hoc per-channel send via the `notify.<channel>(to, payload, options?)` Proxy facade. Works for any channel registered in `NotificationChannels` (built-in or custom). `to` accepts a `Notifiable` model OR a raw route string (`"x@y.com"`); `payload` is typed per channel via the registry; `options` is the standard `SendOptions`. `notify.channel(name).send(...)` is the runtime escape when the channel name is not a compile-time literal. Type-based preference gating applies when a type is known — explicit via `options.type` OR auto-detected from a database payload's `type` field. For multi-channel sends use `defineNotification` instead — there is no inline `notify(to, { via, ... })` form on purpose. Triggers: `notify.<channel>`, `notify.channel(name)`, `notify.mail`, `notify.database`, "send a one-off notification", "ad-hoc notification", "send an email without defining a notification", "raw email target", "dynamic channel name"; typical import `import { notify } from "@warlock.js/notifications"`. Skip: reusable multi-channel notifications — `@warlock.js/notifications/define-notification/SKILL.md`; configuring channels — `@warlock.js/notifications/configure-notifications/SKILL.md`.
|
|
16
16
|
- [use-in-app](@warlock.js/notifications/use-in-app/SKILL.md): Use the `inApp` facade for the in-app/database channel's READ side: `inApp.configure({ model: Notification })` or `{ repository: myRepo }` binds the store AND returns the channel; `inApp.list / listUnread / countUnread / markAsRead / markAsUnread` are RECIPIENT-SCOPED by construction (no IDOR — `markAsRead(user, id)` cannot flip another user's row even with a foreign id). `countUnread` uses `RepositoryManager.countCached` for the badge fast-path. Triggers: `inApp.configure`, `inApp.list`, `inApp.listUnread`, `inApp.countUnread`, `inApp.markAsRead`, `inApp.markAsUnread`, `BaseNotificationsRepository`, `DatabaseNotification`, `NotificationsFilter`, "in-app notifications", "mark notification as read", "unread count", "notification badge", "IDOR-safe markAsRead"; typical import `import { inApp } from "@warlock.js/notifications"`. Skip: writing notifications (use `defineNotification` or `notify.database`) — `@warlock.js/notifications/define-notification/SKILL.md`; the migration columns — `@warlock.js/notifications/write-notification-migration/SKILL.md`; wiring it into config — `@warlock.js/notifications/configure-notifications/SKILL.md`.
|
|
17
17
|
- [write-notification-migration](@warlock.js/notifications/write-notification-migration/SKILL.md): Create the notifications table with the `notificationColumns(Notification)` factory + cascade `Migration.create`. Column NAMES come from the model's `columnMap` (recipient / tenant / readAt / isRead); the fixed columns are `type` / `title` / `body` / `payload` / `idempotency_key`. Read-state follows columnMap presence: `readAt` → nullable timestamp, `isRead` → indexed boolean, both → both. Defaults to `user_id` + `read_at` when no columnMap. Spread + extend for extras (FK references, composite indexes). Triggers: `notificationColumns`, `Migration.create` for notifications, "create the notifications table", "notification migration", "add organization_id to notifications", `is_read` column, `read_at` column, `idempotency_key` column; typical import `import { Migration } from "@warlock.js/cascade"; import { notificationColumns } from "@warlock.js/notifications"`. Skip: generic cascade migration writing — `@warlock.js/cascade/write-migration/SKILL.md`; the model itself — `@warlock.js/notifications/use-in-app/SKILL.md`.
|
package/package.json
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
"environment": "server"
|
|
6
6
|
},
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@warlock.js/cache": "5.
|
|
9
|
-
"@warlock.js/cascade": "5.
|
|
10
|
-
"@warlock.js/core": "5.
|
|
11
|
-
"@warlock.js/logger": "5.
|
|
8
|
+
"@warlock.js/cache": "5.13.0",
|
|
9
|
+
"@warlock.js/cascade": "5.13.0",
|
|
10
|
+
"@warlock.js/core": "5.13.0",
|
|
11
|
+
"@warlock.js/logger": "5.13.0"
|
|
12
12
|
},
|
|
13
13
|
"optionalDependencies": {
|
|
14
|
-
"@warlock.js/herald": "5.
|
|
14
|
+
"@warlock.js/herald": "5.13.0"
|
|
15
15
|
},
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
],
|
|
28
28
|
"author": "hassanzohdy",
|
|
29
29
|
"license": "MIT",
|
|
30
|
-
"version": "5.
|
|
30
|
+
"version": "5.13.0",
|
|
31
31
|
"main": "./cjs/index.cjs",
|
|
32
32
|
"module": "./esm/index.mjs",
|
|
33
33
|
"types": "./esm/index.d.mts",
|
|
@@ -1,81 +1,102 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: queue-notifications
|
|
3
|
-
description:
|
|
3
|
+
description: "Send notifications asynchronously through the herald backend or the BullMQ adapter. Configure a QueueDispatcher in config/notifications.ts, then use notif.queue(to, data, options?) to enqueue rendered jobs. Herald uses heraldQueue() and startNotificationsWorker(); queueNotificationDispatcher() from @warlock.js/queue/notifications uses BullMQ, supports retries, and honours SendOptions.delay. Without a queue configured, .queue() rejects NoQueueDispatcherError. Triggers: heraldQueue, startNotificationsWorker, queueNotificationDispatcher, QueueDispatcher, .queue(, async notifications, queue notifications, notification worker, background notifications, notifications.dispatch. Skip: synchronous sends - @warlock.js/notifications/define-notification/SKILL.md; herald itself - @warlock.js/herald/*."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Queue notifications (async)
|
|
7
7
|
|
|
8
|
-
Move slow channels (SMTP, HTTP) off the request path. `.queue()`
|
|
9
|
-
|
|
8
|
+
Move slow channels (SMTP, HTTP) off the request path. `.queue()` renders the
|
|
9
|
+
payload and resolves the route before passing a serializable job to a dispatcher.
|
|
10
10
|
|
|
11
|
-
## Wire the dispatcher
|
|
11
|
+
## Wire the herald dispatcher
|
|
12
12
|
|
|
13
13
|
```ts title="src/config/notifications.ts"
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
type NotificationConfig,
|
|
16
|
+
heraldQueue,
|
|
17
|
+
inApp,
|
|
18
|
+
mailChannel,
|
|
19
|
+
} from "@warlock.js/notifications";
|
|
15
20
|
import { Notification } from "app/notifications/notification.model";
|
|
16
21
|
|
|
17
22
|
const config: NotificationConfig = {
|
|
18
23
|
channels: { mail: mailChannel(), database: inApp.configure({ model: Notification }) },
|
|
19
|
-
queue: heraldQueue(),
|
|
24
|
+
queue: heraldQueue(),
|
|
20
25
|
};
|
|
21
26
|
|
|
22
|
-
export default config;
|
|
27
|
+
export default config;
|
|
23
28
|
```
|
|
24
29
|
|
|
25
|
-
`heraldQueue({ channel?, broker? })` publishes to `"notifications.dispatch"`
|
|
26
|
-
the default broker unless overridden. It lazy-imports `@warlock.js/herald`;
|
|
27
|
-
that package
|
|
30
|
+
`heraldQueue({ channel?, broker? })` publishes to `"notifications.dispatch"`
|
|
31
|
+
on the default broker unless overridden. It lazy-imports `@warlock.js/herald`;
|
|
32
|
+
if that package is missing, the first `.queue()` throws an install message.
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
config error, not a silent no-op.
|
|
34
|
+
## Use BullMQ for delayed or retried delivery
|
|
31
35
|
|
|
32
|
-
|
|
36
|
+
With `@warlock.js/queue` configured, use its notification dispatcher instead
|
|
37
|
+
of the herald dispatcher:
|
|
33
38
|
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
```ts title="src/config/notifications.ts"
|
|
40
|
+
import { type NotificationConfig, mailChannel } from "@warlock.js/notifications";
|
|
41
|
+
import { queueNotificationDispatcher } from "@warlock.js/queue/notifications";
|
|
42
|
+
|
|
43
|
+
const config: NotificationConfig = {
|
|
44
|
+
channels: { mail: mailChannel() },
|
|
45
|
+
queue: queueNotificationDispatcher({ attempts: 3 }),
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export default config;
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The BullMQ adapter honours `SendOptions.delay`: numeric delays are seconds and
|
|
52
|
+
string delays use the normal duration syntax, such as `"10m"`. It also supports
|
|
53
|
+
BullMQ retries through `attempts` and `backoff`.
|
|
54
|
+
|
|
55
|
+
## Run the herald worker
|
|
56
|
+
|
|
57
|
+
In a worker entrypoint (or the web process), after the config and herald broker
|
|
58
|
+
are up:
|
|
36
59
|
|
|
37
60
|
```ts
|
|
38
61
|
import { startNotificationsWorker } from "@warlock.js/notifications";
|
|
39
62
|
|
|
40
|
-
await startNotificationsWorker();
|
|
63
|
+
await startNotificationsWorker();
|
|
41
64
|
```
|
|
42
65
|
|
|
43
|
-
The worker
|
|
44
|
-
`channel.send({ payload, route, options })`. The
|
|
45
|
-
|
|
46
|
-
worker needs no recipient model.
|
|
66
|
+
The worker looks up the channel by name and runs
|
|
67
|
+
`channel.send({ payload, route, options })`. The worker needs no recipient model
|
|
68
|
+
because rendering happened at enqueue time.
|
|
47
69
|
|
|
48
70
|
## Send
|
|
49
71
|
|
|
50
72
|
```ts
|
|
51
|
-
await orderShipped.queue(user, { order });
|
|
73
|
+
await orderShipped.queue(user, { order });
|
|
52
74
|
await orderShipped.queue(buyers, { order }, { delay: "10m" });
|
|
53
|
-
await notify.mail(user, payload, {
|
|
75
|
+
await notify.mail(user, payload, {/* synchronous - notify.* does not queue */});
|
|
54
76
|
```
|
|
55
77
|
|
|
56
|
-
`.queue()` renders
|
|
57
|
-
|
|
78
|
+
`.queue()` renders per recipient and enqueues one job per recipient. Without a
|
|
79
|
+
configured dispatcher, it rejects `NoQueueDispatcherError`.
|
|
58
80
|
|
|
59
81
|
## Idempotency
|
|
60
82
|
|
|
61
|
-
Pass `idempotencyKey` so a redelivered
|
|
62
|
-
in-app row
|
|
83
|
+
Pass `idempotencyKey` so a redelivered or retried job does not create a duplicate
|
|
84
|
+
in-app row. `createFor` finds or creates the row by that key.
|
|
63
85
|
|
|
64
86
|
```ts
|
|
65
87
|
await orderShipped.queue(user, { order }, { idempotencyKey: `ship:${order.id}` });
|
|
66
88
|
```
|
|
67
89
|
|
|
68
|
-
##
|
|
90
|
+
## Current limits
|
|
69
91
|
|
|
70
|
-
-
|
|
71
|
-
immediately.
|
|
72
|
-
-
|
|
73
|
-
|
|
74
|
-
- Rate-limit budget is consumed at
|
|
75
|
-
`RateLimiter` docstring).
|
|
92
|
+
- With the herald backend, `delay` is carried on the job but not honoured; the
|
|
93
|
+
worker delivers immediately. Use the BullMQ adapter for delayed delivery.
|
|
94
|
+
- Herald has no retry or dead-letter handling yet; failed `channel.send` calls
|
|
95
|
+
are logged and acknowledged.
|
|
96
|
+
- Rate-limit budget is consumed at enqueue time for queued sends.
|
|
76
97
|
|
|
77
98
|
## See also
|
|
78
99
|
|
|
79
|
-
- [`define-notification/SKILL.md`](../define-notification/SKILL.md)
|
|
80
|
-
- [`configure-notifications/SKILL.md`](../configure-notifications/SKILL.md)
|
|
81
|
-
- [`@warlock.js/herald/herald-basics/SKILL.md`](../../../herald/skills/herald-basics/SKILL.md)
|
|
100
|
+
- [`define-notification/SKILL.md`](../define-notification/SKILL.md) - `.queue()` on a defined notification.
|
|
101
|
+
- [`configure-notifications/SKILL.md`](../configure-notifications/SKILL.md) - the `queue` config slot.
|
|
102
|
+
- [`@warlock.js/herald/herald-basics/SKILL.md`](../../../herald/skills/herald-basics/SKILL.md) - connecting the broker.
|