Task 1-3: Firebase Listener Health Check Scheduled
Phase: 1 - Observability Priority: Medium Module:
firebaselistenerDepends on: Không có Reference:docs/BountyHunter-Backend/details/feature-batch-async-processing/SPEC.md
Background
Firebase listeners trong firebaselistener module không có health monitoring. Nếu Firebase SDK mất kết nối, listeners ngừng hoạt động mà không có alert.
Tasks
File mới: firebaselistener/service/FirebaseHealthCheckService.java
DI Note:
FirebaseHealthCheckServiceis a Spring-managed@Servicebean.FirebaseDatabase.getInstance()is a static SDK call — no Spring injection needed for Firebase itself. Ensure the Firebase Admin SDK dependency is on the classpath (firebase-adminjar). Required imports: -com.google.firebase.database.DatabaseReference-com.google.firebase.database.FirebaseDatabase-com.google.firebase.database.DataSnapshot-com.google.firebase.database.DatabaseError-com.google.firebase.database.ValueEventListener-org.springframework.scheduling.annotation.Scheduled-java.time.Instant
@Service
@Slf4j
public class FirebaseHealthCheckService {
private volatile boolean lastHealthy = true;
private Instant lastHealthCheckTime = Instant.now();
@Scheduled(fixedDelay = 30000)
public void checkFirebaseConnection() {
try {
DatabaseReference connRef = FirebaseDatabase.getInstance()
.getReference(".info/connected");
connRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
Boolean connected = snapshot.getValue(Boolean.class);
lastHealthCheckTime = Instant.now();
if (Boolean.TRUE.equals(connected)) {
if (!lastHealthy) {
log.info("[FIREBASE_HEALTH] Connection restored");
}
lastHealthy = true;
} else {
log.error("[FIREBASE_HEALTH] Firebase reports NOT connected!");
lastHealthy = false;
}
}
@Override
public void onCancelled(DatabaseError error) {
log.error("[FIREBASE_HEALTH] Health check cancelled: {}", error.getMessage());
lastHealthy = false;
}
});
} catch (Exception e) {
log.error("[FIREBASE_HEALTH] Exception during health check", e);
lastHealthy = false;
}
}
public boolean isHealthy() {
return lastHealthy;
}
}
- [ ] Expose health status via Spring Actuator
HealthIndicator - [ ] Alert khi
lastHealthy=falsepersists > 2 checks
Verification / Acceptance Criteria
- [ ]
FirebaseHealthCheckServicebean starts without errors;checkFirebaseConnection()scheduler fires every 30 s - [ ] When Firebase is reachable,
isHealthy()returnstrueand logs[FIREBASE_HEALTH] Connection restoredonly on recovery (not on every tick) - [ ] When Firebase connection is simulated as unavailable (mock
FirebaseDatabase),isHealthy()returnsfalseand an error is logged - [ ]
lastHealthCheckTimeis updated on every successfulonDataChangecallback - [ ] Spring Actuator
HealthIndicator(follow-up item) reportsDOWNwhenisHealthy() == false
Files to Create
firebaselistener/service/FirebaseHealthCheckService.java