Appearance
Queueing Notifications
Basic Queueing
Notifications can be delayed and processed asynchronously using queues:
ts
await notify(user, invoicePaid)
.onQueue('notifications')
.delay(300) // 5 minutes delay
.afterCommit()This requires the @holo-js/queue package to be installed. If the configured queue connection uses an async driver, production also needs a supervised queue worker. See Deployment for host selection and Queue Workers for worker commands.
Queue Configuration
You can configure default queue settings in your notifications configuration:
ts
// config/notifications.ts
export default defineNotificationsConfig({
default: 'database',
queue: {
connection: 'default',
queue: 'notifications',
// Whether to delay dispatch until after database commits
afterCommit: true
},
channels: {
database: {
driver: 'database',
table: 'notifications'
}
}
})Queue Options
Delayed Delivery
ts
// Delay all channels by 5 minutes
await notify(user, invoicePaid)
.delay(5 * 60)
// Delay specific channels
await notify(user, invoicePaid)
.delayFor('email', 10 * 60) // Email delayed 10 minutes
.delayFor('broadcast', 0) // Broadcast immediately
// Delay using a Date object
await notify(user, invoicePaid)
.delay(new Date(Date.now() + 3600000))Notification Queue Defaults
You can set queue defaults for every queued channel in your notification definition:
ts
interface InvoicePaidNotification {
readonly invoiceId: string
readonly invoiceNumber: string
}
const invoicePaid = defineNotification({
type: 'invoice-paid',
via() {
return ['email', 'database', 'broadcast']
},
queue: {
queue: 'notifications',
afterCommit: true,
},
build: {
email(data: InvoicePaidNotification) {
return {
subject: `Invoice #${data.invoiceNumber} paid`,
lines: ['Your invoice has been successfully paid.'],
}
},
database(data: InvoicePaidNotification) {
return {
data: {
invoiceId: data.invoiceId,
invoiceNumber: data.invoiceNumber,
},
}
},
broadcast(data: InvoicePaidNotification) {
return {
event: 'invoice.paid',
data: {
invoiceId: data.invoiceId,
invoiceNumber: data.invoiceNumber,
},
}
},
},
})How Queueing Works
- When
.onQueue()is called, one queue job is created per recipient and per channel - Each queue job contains:
- The notification definition
- The recipient information
- Channel-specific payload data
- Queue workers process jobs by:
- Reconstructing the notification
- Sending it through the appropriate channel
- If
.afterCommit()is used, notifications are only queued after database transactions commit - Channel failures are isolated - if one channel fails, others continue to process