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:
@@ -3,10 +3,21 @@ import { MessageService } from './message.service';
|
||||
import { MessageGateway } from './message.gateway';
|
||||
import { OutboxModule } from '../outbox/outbox.module';
|
||||
import { PresenceService } from '../notifications/presence.service';
|
||||
import { RedisPresenceService } from '../notifications/redis-presence.service';
|
||||
import { PRESENCE_PORT } from '../notifications/presence.port';
|
||||
|
||||
/**
|
||||
* PRESENCE_PORT is single-instance in-memory by default; with REDIS_URL set it's Redis-backed so
|
||||
* "who is viewing what" is shared across replicas (mirrors the socket.io Redis adapter gating).
|
||||
*/
|
||||
const presenceProvider = {
|
||||
provide: PRESENCE_PORT,
|
||||
useFactory: () => (process.env.REDIS_URL ? new RedisPresenceService(process.env.REDIS_URL) : new PresenceService()),
|
||||
};
|
||||
|
||||
@Module({
|
||||
imports: [OutboxModule],
|
||||
providers: [MessageService, MessageGateway, PresenceService],
|
||||
exports: [MessageService, PresenceService],
|
||||
providers: [MessageService, MessageGateway, presenceProvider],
|
||||
exports: [MessageService, PRESENCE_PORT],
|
||||
})
|
||||
export class MessageModule {}
|
||||
|
||||
Reference in New Issue
Block a user