Skip to content

Task 3-2: Health Check Endpoint cho JMS Listener Status

Phase: 3 - Dynamic Queue Priority: Low Module: batch Depends on: task-3-1 Reference: docs/BountyHunter-Backend/details/feature-game-room-management/SPEC.md

Background

Không có cách nào để biết nhanh số lượng listeners đang chạy, listener nào đang down, hay số queues đã được register. Cần endpoint để ops team có thể inspect.

Tasks

File mới: batch/actuator/JmsListenerHealthIndicator.java

DI Note: JmsListenerEndpointRegistry là một Spring bean tự động được tạo khi dùng @EnableJms. Inject vào constructor — đây là cách Spring khuyến nghị cho HealthIndicator implementations. Không cần @Autowired annotation khi có duy nhất 1 constructor.

Clarification: Tên bean jmsListenerHealth trong /actuator/health response được Spring tự động derive từ tên class: JmsListenerHealthIndicatorjmsListenerHealth. Không cần cấu hình thêm.

Import cần thiết: - org.springframework.boot.actuate.health.HealthIndicator - org.springframework.boot.actuate.health.Health - org.springframework.jms.config.JmsListenerEndpointRegistry - org.springframework.jms.listener.MessageListenerContainer

@Component
public class JmsListenerHealthIndicator implements HealthIndicator {

    private final JmsListenerEndpointRegistry registry;

    // Constructor injection — Spring auto-injects JmsListenerEndpointRegistry bean
    public JmsListenerHealthIndicator(JmsListenerEndpointRegistry registry) {
        this.registry = registry;
    }

    @Override
    public Health health() {
        Collection<MessageListenerContainer> containers = registry.getListenerContainers();
        long runningCount = containers.stream().filter(MessageListenerContainer::isRunning).count();
        long stoppedCount = containers.size() - runningCount;

        Map<String, Object> details = new LinkedHashMap<>();
        details.put("total", containers.size());
        details.put("running", runningCount);
        details.put("stopped", stoppedCount);

        if (stoppedCount > 0) {
            // List stopped listener IDs để ops team biết listener nào bị down
            List<String> stoppedIds = registry.getListenerContainerIds().stream()
                .filter(id -> !registry.getListenerContainer(id).isRunning())
                .collect(Collectors.toList());
            details.put("stopped_ids", stoppedIds);
            return Health.down().withDetails(details).build();
        }

        return Health.up().withDetails(details).build();
    }
}
  • [ ] Tạo file tại đúng package path: com.figpop.batch.actuator
  • [ ] Verify accessible tại GET /actuator/health → response chứa jmsListenerHealth component
  • [ ] Đảm bảo management.endpoint.health.show-details=always trong application.yaml nếu muốn thấy details

Verification / Acceptance Criteria

  • [ ] GET /actuator/health trả về HTTP 200 với jmsListenerHealth.status: "UP" khi tất cả listeners running
  • [ ] Khi dừng 1 listener thủ công (hoặc simulate stopped container), GET /actuator/health trả về status: "DOWN" với stopped_ids liệt kê ID bị dừng
  • [ ] details.total = tổng số listeners đã đăng ký (bao gồm cả listeners được đăng ký dynamically từ task-3-1)
  • [ ] details.running + details.stopped = details.total (số học đúng)
  • [ ] Unit test: mock registry với 3 running + 1 stopped → verify Health.down() với stopped_ids = [stoppedId]
  • [ ] Unit test: mock registry với tất cả running → verify Health.up()
  • [ ] Class compile được với Spring Boot Actuator dependency (kiểm tra pom.xml của module batch)

Files to Create

  • batch/src/main/java/com/figpop/batch/actuator/JmsListenerHealthIndicator.java