feat(presence): Redis-backed presence for multi-replica prod
Extract a PresencePort seam (async setFocus/clearSocket/isViewing) with two impls: the existing in-memory Map (dev, single instance) and a new RedisPresenceService (prod). MessageModule provides PRESENCE_PORT via a REDIS_URL-gated factory — same pattern as the socket.io Redis adapter — so 'who is viewing what' is shared across replicas and the notification projector's presence gate works at N>1. Gateway + projector inject the port; isViewing is now awaited. Presence spec updated to async (passing). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import { PrismaService } from '../prisma/prisma.service';
|
||||
import { OutboxBus } from '../outbox/outbox.bus';
|
||||
import { DlqService } from '../outbox/dlq.service';
|
||||
import { ProjectionCursorService } from '../projection/projection-cursor.service';
|
||||
import { PresenceService } from './presence.service';
|
||||
import { PRESENCE_PORT, type PresencePort } from './presence.port';
|
||||
import { NOTIFICATION_PORT, type NotificationPort } from './notification.port';
|
||||
|
||||
interface MsgData {
|
||||
@@ -40,7 +40,7 @@ export class NotificationProjector implements OnModuleInit {
|
||||
private readonly bus: OutboxBus,
|
||||
private readonly dlq: DlqService,
|
||||
private readonly cursor: ProjectionCursorService,
|
||||
private readonly presence: PresenceService,
|
||||
@Inject(PRESENCE_PORT) private readonly presence: PresencePort,
|
||||
@Inject(NOTIFICATION_PORT) private readonly port: NotificationPort,
|
||||
) {}
|
||||
|
||||
@@ -123,7 +123,7 @@ export class NotificationProjector implements OnModuleInit {
|
||||
if (!(alwaysNotify || mentioned || repliedToMe)) continue;
|
||||
|
||||
// gate 2 — presence
|
||||
if (userId && this.presence.isViewing(userId, data.threadId)) continue;
|
||||
if (userId && (await this.presence.isViewing(userId, data.threadId))) continue;
|
||||
|
||||
// gate 3 — mute
|
||||
if (p.muted) continue;
|
||||
|
||||
Reference in New Issue
Block a user