Midday / apps /worker /src /queues /notifications.config.ts
Jules
Final deployment with all fixes and verified content
c09f67c
import { createLoggerWithContext } from "@midday/logger";
import type { QueueOptions, WorkerOptions } from "bullmq";
import { getRedisConnection } from "../config";
import { DEFAULT_JOB_OPTIONS } from "../config/job-options";
import type { QueueConfig } from "../types/queue-config";
const logger = createLoggerWithContext("worker:queue:notifications");
/**
* Queue options for notifications queue
*/
const notificationsQueueOptions: QueueOptions = {
connection: getRedisConnection(),
defaultJobOptions: {
...DEFAULT_JOB_OPTIONS,
removeOnComplete: {
age: 24 * 3600, // Keep completed jobs for 24 hours
count: 1000, // Keep max 1000 completed jobs
},
removeOnFail: {
age: 7 * 24 * 3600, // Keep failed jobs for 7 days
},
},
};
/**
* Worker options for notifications queue
* Rate limited to 5 notifications per second to prevent overwhelming
* email providers, push notification services, and external integrations
*/
const notificationsWorkerOptions: WorkerOptions = {
connection: getRedisConnection(),
concurrency: 5,
lockDuration: 30000, // 30 seconds - notifications are quick
stalledInterval: 60000, // 1 minute
limiter: {
max: 5, // 5 notifications per second
duration: 1000,
},
};
/**
* Notifications queue configuration
* Unified queue for all notification types:
* - insight_ready
* - inbox_new
* - document_uploaded, document_processed
* - invoice_paid, invoice_overdue, invoice_sent, etc.
* - recurring_series_completed, recurring_series_paused
*/
export const notificationsQueueConfig: QueueConfig = {
name: "notifications",
queueOptions: notificationsQueueOptions,
workerOptions: notificationsWorkerOptions,
eventHandlers: {
onCompleted: (job) => {
logger.info("Job completed", { jobName: job.name, jobId: job.id });
},
onFailed: (job, err) => {
logger.error("Job failed", {
jobName: job?.name,
jobId: job?.id,
error: err.message,
});
},
},
};