Architecture: hbf-lcm
C4 Component Diagram
Key Flows
Livechat Request (end-user requests human agent)
- hbf-bot sends
POST /livechat-requests(LCM JWT token) with the end-user and organization details. LivechatCoreController.postRequest()callsLivechatCoreService.getOrganizationCluster(orgId)to resolve the mode (PUBLIC or SEMI-PRIVATE).- The appropriate
RestService.saveAndSendRequest()persists theLivechatRequestto MySQL. OutgoingServiceemits asendEventevent viaEventEmitter, whichSocketsGatewayforwards to the organization room — all connected agents for that org receive the new request notification.
Agent Accepts Request and Starts Conversation
- Agent's hbf-console socket sends an
eventwith typeACCEPT_REQUESTand the request id. SocketsGateway.receiveEvent()delegates toIncomingService.onReceiveEventFromAgent().- The
IncomingServicetransitions the request toACCEPTED, creates aLivechatConversation, and saves the agent as a participant. - Both the bot (via
BotClientService) and connected agents (viasendEventthrough the gateway) are notified of the conversation start.
Message Flow (agent to end-user)
- Agent sends
messagesocket event withlivechatConversation.idand text. SocketsGateway.receiveMessage()callsIncomingService.onReceiveMessageFromAgent().- The service persists the
LivechatMessage, then callsBotClientServiceto push the message to hbf-bot. - The gateway also emits
messageto the conversation's agent rooms so all participants see the message.
Message Flow (end-user to agent, via hbf-bot)
- hbf-bot sends
POST /organizations/:orgId/livechat-messages(LCM JWT token). LivechatCoreController.postMessage()callsRestService.saveAndSendMessage().- The message is persisted, then a
sendMessageevent is emitted viaEventEmitter. SocketsGateway.sendMessage()delivers it to the agent room.
Monitor: Request Expiry
MonitorServiceruns onMONITOR_INTERVAL_SECONDSinterval.- It acquires a pessimistic DB lock via
LivechatEnvironmentto prevent duplicate runs in multi-instance deploys. - For each
NEWlivechat request, it checks the per-tenant plugin expiration threshold (from hbf-core, with fallback toMONITOR_REQUEST_EXPIRATION_FALLBACK_SECONDS). - If
now - requestedDate > threshold, it callshandleRequestMissed()which sets the request toMISSEDand notifies both the bot and agents.
Socket Room Model
Each connected agent socket joins three room types on authentication:
- Personal room:
orgId:userId— targeted events for this agent only. - Organization room:
orgId— broadcasts to all agents in the org. - Group rooms: one per group the agent belongs to in this org.
Outbound events use server.to(room).emit(channel, data). This room model scales horizontally via the Redis adapter when REDIS_ENABLE=true.