Task 1-1: Chuẩn hóa Error Events cho Matching
Phase: 1 Priority: Medium Module:
websocketDepends on: Không có Blocks: task-3-1, task-3-2, task-3-3 Reference: docs/BountyHunter-Backend/details/feature-matching-matchmaking/SPEC.md
Background
Error events từ matching/pool/invitation dùng VALIDATE_GAME chung với reason strings không chuẩn hóa. Cần tạo constants và đảm bảo leave graceful.
Tasks
1. Tạo MatchingReasonCode constants
DI Note:
MatchingReasonCodelà utility class với constants — không cần inject, không cần@Component. Các consumer handlers (MatchMatchingCmdConsumer,OpponentPoolCmdHandler,InvitationCmdConsumer) đã injectBroadcastService(hoặc tương đương) để gửi events — chỉ cần replace hardcoded string bằng constant, không cần thêm injection mới.
File mới: common/src/main/java/com/figpop/common/constants/MatchingReasonCode.java
public final class MatchingReasonCode {
private MatchingReasonCode() {} // Prevent instantiation
public static final String INVALID_PRIZE_IDS = "INVALID_PRIZE_IDS";
public static final String INVALID_PRIZE_ALLOCATION_TYPE = "INVALID_PRIZE_ALLOCATION_TYPE";
public static final String INVITATION_EXPIRED = "INVITATION_EXPIRED";
public static final String INVITATION_NOT_FOUND = "INVITATION_NOT_FOUND";
public static final String TARGET_USER_BUSY = "TARGET_USER_BUSY";
// ... thêm sau khi audit tất cả VALIDATE_GAME usages
}
2. Audit và replace hardcoded strings
- [ ] Grep tất cả
VALIDATE_GAMEbroadcasts trong source code:grep -rn "VALIDATE_GAME" websocket/ application-core/ - [ ] Replace với
MatchingReasonCode.*trong: MatchMatchingCmdConsumer.javaOpponentPoolCmdHandler.javaInvitationCmdConsumer.javaCreateRoomService.java(matching paths)- [ ] Thêm tất cả reason codes tìm được vào
MatchingReasonCode.java
3. Đảm bảo leave graceful
DI Note:
MatchMatchingCmdConsumerinjectCreateRoomServiceđể gọileaveAutoMatchMatching(). Exception type cần xác nhận (có thể làMatchingRecordNotFoundException,NotFoundException, hoặc custom exception từapplication-core). Kiểm tra packagecom.figpop.common.exceptionđể tìm đúng class name.
File: websocket/handler/consumer_handler/MatchMatchingCmdConsumer.java
@OnCmd("LEAVE_QUEUE_MATCH_MATCHING")
public void onLeaveAutoMatching(JSONObject objectMessage, String userId) {
try {
String settingId = objectMessage.getString("playable_game_booth_setting_id");
String prizeId = objectMessage.optString("prize_id", null);
createRoomService.leaveAutoMatchMatching(userId, settingId, prizeId);
// Optional: broadcast success
} catch (MatchingRecordNotFoundException e) {
// Graceful: log warning, không broadcast error về client
LOGGER.warn("[MATCHING] No matching record found for user {} - ignoring leave", userId);
}
}
Verification / Acceptance Criteria
- [ ]
MatchingReasonCode.javatồn tại tại pathcommon/constants/và compile thành công - [ ] Grep
VALIDATE_GAMEtrong các consumer handlers → tất cả hardcoded strings đã được thay bằngMatchingReasonCode.* - [ ] Khi
LEAVE_QUEUE_MATCH_MATCHINGgửi mà user không trong queue → server log WARN, không broadcast error tới client - [ ] Unit test:
MatchingReasonCode.INVALID_PRIZE_IDS.equals("INVALID_PRIZE_IDS")= true
Files to Modify
common/constants/MatchingReasonCode.java(new)websocket/handler/consumer_handler/MatchMatchingCmdConsumer.javawebsocket/handler/consumer_handler/OpponentPoolCmdHandler.javawebsocket/handler/consumer_handler/InvitationCmdConsumer.java