Thiết kế: IoT Receiver Service Feature
1. Tổng quan kiến trúc
flowchart TB
subgraph IoT["Physical Layer"]
CM["Crane Machine (IoT)"]
end
subgraph CS["BountyHunter-ControlServer"]
CSApp["Control Server App\n(WebSocket bridge)"]
end
subgraph MQ["ActiveMQ Artemis"]
Q1["queue-control-server-gameplay\nconcurrency: 1-50"]
Q2["queue-control-server-health-check\nconcurrency: 1-50"]
Q3["queue-machine_history_log\nconcurrency: 1-1"]
end
subgraph RS["receiver-service (port 8088)"]
GL["JMSReceiverGameplayMachineListener"]
HL["JMSReceiverHealthCheckMachineListener"]
LL["JMSReceiverLogMachineListener"]
BATCH["CraneMachineCheckStatusBatchConfig"]
end
subgraph Core["application-core"]
GS["IGameService\n(startGame, endGame, countDown)"]
CMS["CraneMachineService\n(status, connect, disconnect)"]
SLACK["SlackNotificationService"]
MHLR["MachineHistoryLogRepository"]
MRRLR["MachineReceivedResultLogRepository"]
end
CM <-->|WebSocket| CSApp
CSApp -->|publish| Q1 & Q2 & Q3
Q1 --> GL
Q2 --> HL
Q3 --> LL
GL --> GS
HL --> CMS & SLACK
LL --> CMS & MHLR & MRRLR & SLACK
BATCH --> CMS
GS -->|"WS broadcast"| Player["Players (WebSocket)"]
2. Gameplay event flow
sequenceDiagram
participant CM as Crane Machine
participant CS as ControlServer
participant MQ as ActiveMQ
participant GL as JMSReceiverGameplayListener
participant GS as IGameService
participant Redis as Redis (Room State)
participant WS as WebSocket (Players)
CM-->>CS: Game ended (win)
CS->>MQ: publish {mac_ip, message_type: END_GAME, data: {game_res: 1}}
MQ->>GL: receiveMessage(json)
GL->>GL: deserialize → macIp, MessageType.END_GAME
GL->>GS: endGameSuccess(macIp, gameResult=1, false)
GS->>Redis: get room by macIp
GS->>Redis: update room state = FINISHED
GS->>WS: broadcast GAME_END to players
GS->>MQ: publish prize allocation message
3. Health check & Slack alert flow
sequenceDiagram
participant CM as Crane Machine
participant CS as ControlServer
participant MQ as ActiveMQ
participant HL as JMSReceiverHealthCheckListener
participant CMS as CraneMachineService
participant DB as MySQL
participant Slack as Slack
CM-->>CS: Camera error
CS->>MQ: {mac_ip, message_type: CAM_STATUS_REPORT, data: {cam_position: "TOP", cam_status: "ERROR"}}
MQ->>HL: receiveMessage(json)
HL->>CMS: camStatusReport(macIp, reportData)
CMS->>DB: update camera status
alt cam_status != OK
HL->>Slack: sendCamErrorNotification(macIp, camPosition, camStatus)
end
Note over CM,Slack: Error code 81 - auto end game
CM-->>CS: ERROR_REPORT {error_code: 81}
CS->>MQ: publish ERROR_REPORT
MQ->>HL: receiveMessage
HL->>CMS: machineErrorReport(reportData, macIp)
CMS->>DB: log error
HL->>GS: endGameSuccess(macIp, 1, true) # force end with error flag
HL->>Slack: sendMachineErrorNotification(macIp, errorText, errorCode)
4. Log persistence flow
sequenceDiagram
participant CS as ControlServer
participant MQ as ActiveMQ
participant LL as JMSReceiverLogMachineListener
participant CMS as CraneMachineService
participant DB as MySQL
participant Slack as Slack
CS->>MQ: {type: SAVE_MACHINE_HISTORY_LOG, mac: "AA:BB:...", log_type: DISCONNECTED}
MQ->>LL: receiveMessage(json)
LL->>LL: resolve boothId from machineMac\n(craneMachineService.findByMac → groupLabel-groupNumber)
LL->>LL: set envType, boothId, noteMap
LL->>DB: machineHistoryLogRepository.save(model)
alt log_type == DISCONNECTED
LL->>Slack: notifySlackMachineDisconnect(machineMac)
end
5. concurrency design
| Queue |
Concurrency |
Lý do |
queue-control-server-gameplay |
1-50 |
High throughput, parallel machines, IGameService thread-safe |
queue-control-server-health-check |
1-50 |
Parallel machines, health events independent |
queue-machine_history_log |
1-1 |
Sequential logging per machine, avoid DB write conflicts |
6. Error handling
| Tình huống |
Xử lý |
| JSON parse error |
BadRequestException thrown → message goes to DLQ |
| macIp không tìm thấy trong DB |
boothId = "UNKNOWN", vẫn persist log |
IGameService throws ControlServerMessageFail |
Log error, không re-throw (message ack'd) |
endGameSuccess throws exception (error code 81 path) |
catch Exception → log error, không re-throw |
| Slack notification fails |
Log error, không affect main flow |