diff --git a/apps/server/src/common/events/event.contants.ts b/apps/server/src/common/events/event.contants.ts index 3a0ecba17..6f0404c46 100644 --- a/apps/server/src/common/events/event.contants.ts +++ b/apps/server/src/common/events/event.contants.ts @@ -15,6 +15,7 @@ export enum EventName { WORKSPACE_CREATED = 'workspace.created', WORKSPACE_UPDATED = 'workspace.updated', WORKSPACE_DELETED = 'workspace.deleted', + NOTIFICATION_CREATED = 'notification.created', BASE_CREATED = 'base.created', BASE_UPDATED = 'base.updated', diff --git a/apps/server/src/core/notification/notification.service.ts b/apps/server/src/core/notification/notification.service.ts index 1f88bf59e..ab1b88e64 100644 --- a/apps/server/src/core/notification/notification.service.ts +++ b/apps/server/src/core/notification/notification.service.ts @@ -1,5 +1,6 @@ import { Injectable, Logger } from '@nestjs/common'; import { InjectKysely } from 'nestjs-kysely'; +import { EventEmitter2 } from '@nestjs/event-emitter'; import { KyselyDB } from '@docmost/db/types/kysely.types'; import { NotificationRepo } from '@docmost/db/repos/notification/notification.repo'; import { InsertableNotification } from '@docmost/db/types/entity.types'; @@ -8,6 +9,7 @@ import { WsGateway } from '../../ws/ws.gateway'; import { MailService } from '../../integrations/mail/mail.service'; import { NotificationTab, NotificationType, NotificationTypeToSettingKey } from './notification.constants'; import { PagePermissionRepo } from '@docmost/db/repos/page/page-permission.repo'; +import { EventName } from '../../common/events/event.contants'; @Injectable() export class NotificationService { @@ -18,6 +20,7 @@ export class NotificationService { private readonly pagePermissionRepo: PagePermissionRepo, private readonly wsGateway: WsGateway, private readonly mailService: MailService, + private readonly eventEmitter: EventEmitter2, @InjectKysely() private readonly db: KyselyDB, ) {} @@ -34,6 +37,8 @@ export class NotificationService { const notification = await this.notificationRepo.insert(data); + this.eventEmitter.emit(EventName.NOTIFICATION_CREATED, notification); + this.wsGateway.server .to(`user-${data.userId}`) .emit('notification', { id: notification.id, type: notification.type }); diff --git a/apps/server/src/integrations/queue/constants/queue.constants.ts b/apps/server/src/integrations/queue/constants/queue.constants.ts index 4d2a27515..e43a82440 100644 --- a/apps/server/src/integrations/queue/constants/queue.constants.ts +++ b/apps/server/src/integrations/queue/constants/queue.constants.ts @@ -14,6 +14,9 @@ export enum QueueName { // Separate queue for /docmost ask: AI work takes seconds and would // otherwise starve fast inbound event dispatch. SLACK_ASK = '{slack-ask}', + // Outbound notification DMs; isolated so Slack API latency and retries + // never block inbound event dispatch. + SLACK_NOTIFY = '{slack-notify}', BASE_QUEUE = '{base-queue}', } @@ -94,6 +97,7 @@ export enum QueueJob { INTEGRATION_TOKEN_REFRESH = 'integration-token-refresh', SLACK_EVENT = 'slack-event', SLACK_ASK = 'slack-ask', + SLACK_NOTIFICATION = 'slack-notification', BASE_TYPE_CONVERSION = 'base-type-conversion', BASE_CELL_GC = 'base-cell-gc',