Task 3-1: Dynamic Queue Re-registration at Runtime
Phase: 3 - Dynamic Queue Priority: Medium Module:
batchDepends on: Không có Blocks: task-3-2 Reference:docs/BountyHunter-Backend/details/feature-game-room-management/SPEC.md
Background
Khi admin tạo machine mới hoặc game booth setting mới, cần restart toàn bộ batch service để ProgrammaticEndpointRegistration đăng ký listener mới. Gây downtime không cần thiết.
Tasks
File: batch/jms/register_destination/ProgrammaticEndpointRegistration.java
DI Note:
ProgrammaticEndpointRegistrationcần injectmachineRepositoryđể query database, vàJmsListenerEndpointRegistrar(hoặcJmsListenerEndpointRegistry) để đăng ký listener mới dynamically. Kiểm tra class hiện tại xem đã có những dependencies nào được inject.
registeredMachineIdsnên làConcurrentHashSet(hoặcCollections.synchronizedSet(new HashSet<>())) để thread-safe với@Scheduled.
-
[ ] Thêm internal tracking sets vào class:
// Thread-safe sets để track registered IDs private final Set<String> registeredMachineIds = Collections.synchronizedSet(new HashSet<>()); private final Set<String> registeredSettingIds = Collections.synchronizedSet(new HashSet<>()); -
[ ] Extract logic đăng ký listener thành public method — Clarification: method này phải gọi được từ bên ngoài class (e.g., từ admin API hoặc scheduler) và phải idempotent (gọi nhiều lần với cùng ID không gây lỗi):
public void registerMachineListener(String machineId) { // Di chuyển logic đăng ký listener cho machine vào đây // ...existing registration logic... } public void registerSettingListeners(String settingId) { // Di chuyển logic đăng ký listener cho setting vào đây // ...existing registration logic... } -
[ ] Populate
registeredMachineIds/registeredSettingIdskhi@PostConstructđể phản ánh trạng thái ban đầu -
[ ] Thêm scheduled polling check:
// Clarification: machineRepository.findAllActiveMachineIds() phải return chỉ các machine đang active // (không phải tất cả, kể cả deleted/inactive) @Scheduled(fixedDelay = 60000) // poll mỗi 60 giây public void checkForNewMachines() { Set<String> allMachineIds = machineRepository.findAllActiveMachineIds(); allMachineIds.stream() .filter(id -> !registeredMachineIds.contains(id)) .forEach(newId -> { registerMachineListener(newId); registeredMachineIds.add(newId); LOGGER.info("[DYNAMIC_QUEUE] Auto-registered new machine listener: {}", newId); }); } -
[ ] Thêm
@Scheduledtương tự cho settings nếumachineRepository.findAllActiveMachineIds()pattern phù hợp
Verification / Acceptance Criteria
- [ ] Thêm machine mới vào database → trong vòng 60 giây, listener tương ứng được đăng ký mà không cần restart
- [ ] Log
[DYNAMIC_QUEUE] Auto-registered new machine listener: {id}xuất hiện khi có machine mới - [ ] Gọi
registerMachineListener(id)2 lần với cùng ID → không đăng ký duplicate listener (idempotent) - [ ]
registeredMachineIdsđược populate đầy đủ khi application start (không bị trống sau restart) - [ ] Concurrent access vào
registeredMachineIdstừ scheduler không gâyConcurrentModificationException - [ ]
checkForNewMachines()không throw exception khi database không có machine mới - [ ] Task-3-2 (JmsListenerHealthIndicator) có thể thấy listeners được đăng ký dynamically
Files to Modify
batch/jms/register_destination/ProgrammaticEndpointRegistration.java