| 9 | * Used as fallback when REDIS_URL is not configured |
| 10 | */ |
| 11 | export class MemoryRoomManager implements IRoomManager { |
| 12 | private workflowRooms = new Map<string, WorkflowRoom>() |
| 13 | private socketToWorkflow = new Map<string, string>() |
| 14 | private userSessions = new Map<string, UserSession>() |
| 15 | private _io: Server |
| 16 | |
| 17 | constructor(io: Server) { |
| 18 | this._io = io |
| 19 | } |
| 20 | |
| 21 | get io(): Server { |
| 22 | return this._io |
| 23 | } |
| 24 | |
| 25 | async initialize(): Promise<void> { |
| 26 | logger.info('MemoryRoomManager initialized (single-pod mode)') |
| 27 | } |
| 28 | |
| 29 | isReady(): boolean { |
| 30 | return true |
| 31 | } |
| 32 | |
| 33 | async shutdown(): Promise<void> { |
| 34 | this.workflowRooms.clear() |
| 35 | this.socketToWorkflow.clear() |
| 36 | this.userSessions.clear() |
| 37 | logger.info('MemoryRoomManager shutdown complete') |
| 38 | } |
| 39 | |
| 40 | async addUserToRoom(workflowId: string, socketId: string, presence: UserPresence): Promise<void> { |
| 41 | // Create room if it doesn't exist |
| 42 | if (!this.workflowRooms.has(workflowId)) { |
| 43 | this.workflowRooms.set(workflowId, { |
| 44 | workflowId, |
| 45 | users: new Map(), |
| 46 | lastModified: Date.now(), |
| 47 | activeConnections: 0, |
| 48 | }) |
| 49 | } |
| 50 | |
| 51 | const room = this.workflowRooms.get(workflowId)! |
| 52 | room.users.set(socketId, presence) |
| 53 | room.activeConnections++ |
| 54 | room.lastModified = Date.now() |
| 55 | |
| 56 | // Map socket to workflow |
| 57 | this.socketToWorkflow.set(socketId, workflowId) |
| 58 | |
| 59 | // Store session |
| 60 | this.userSessions.set(socketId, { |
| 61 | userId: presence.userId, |
| 62 | userName: presence.userName, |
| 63 | avatarUrl: presence.avatarUrl, |
| 64 | }) |
| 65 | |
| 66 | logger.debug(`Added user ${presence.userId} to workflow ${workflowId} (socket: ${socketId})`) |
| 67 | } |
| 68 |
nothing calls this directly
no outgoing calls
no test coverage detected