Skip to content

Commit 2d380f5

Browse files
fix(health): close basic DB connection before advanced checks and remove shared-map race
1 parent 64d7f31 commit 2d380f5

1 file changed

Lines changed: 26 additions & 12 deletions

File tree

src/main/java/com/iemr/admin/service/health/HealthService.java

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,12 @@
4848
import org.slf4j.Logger;
4949
import org.slf4j.LoggerFactory;
5050
import org.springframework.beans.factory.annotation.Autowired;
51+
import org.springframework.beans.factory.annotation.Value;
5152
import org.springframework.data.redis.core.RedisTemplate;
5253
import org.springframework.stereotype.Service;
5354

55+
import java.util.concurrent.atomic.AtomicInteger;
56+
5457
@Service
5558
public class HealthService {
5659

@@ -87,13 +90,23 @@ public class HealthService {
8790
private final ReentrantReadWriteLock advancedCheckLock = new ReentrantReadWriteLock();
8891
private final AtomicBoolean advancedCheckInProgress = new AtomicBoolean(false);
8992

90-
private static final boolean ADVANCED_HEALTH_CHECKS_ENABLED = true;
93+
@Value("${health.advanced.checks.enabled:true}")
94+
private boolean advancedHealthChecksEnabled;
9195

9296
public HealthService(DataSource dataSource,
9397
@Autowired(required = false) RedisTemplate<String, Object> redisTemplate) {
9498
this.dataSource = dataSource;
9599
this.redisTemplate = redisTemplate;
96-
this.executorService = Executors.newFixedThreadPool(6);
100+
this.executorService = Executors.newFixedThreadPool(2, new java.util.concurrent.ThreadFactory() {
101+
private final AtomicInteger threadCounter = new AtomicInteger(0);
102+
103+
@Override
104+
public Thread newThread(Runnable r) {
105+
Thread t = new Thread(r, "health-check-" + threadCounter.incrementAndGet());
106+
t.setDaemon(true);
107+
return t;
108+
}
109+
});
97110
}
98111

99112
@PreDestroy
@@ -184,11 +197,10 @@ private void cancelFutures(Future<?> mysqlFuture, Future<?> redisFuture) {
184197
}
185198

186199
private void ensurePopulated(Map<String, Object> status, String componentName) {
187-
if (!status.containsKey(STATUS_KEY)) {
188-
status.put(STATUS_KEY, STATUS_DOWN);
189-
status.put(SEVERITY_KEY, SEVERITY_CRITICAL);
190-
status.put(ERROR_KEY, componentName + " health check did not complete in time");
191-
}
200+
201+
status.putIfAbsent(STATUS_KEY, STATUS_DOWN);
202+
status.putIfAbsent(SEVERITY_KEY, SEVERITY_CRITICAL);
203+
status.putIfAbsent(ERROR_KEY, componentName + " health check did not complete in time");
192204
}
193205

194206
private HealthCheckResult checkMySQLHealthSync() {
@@ -199,17 +211,19 @@ private HealthCheckResult checkMySQLHealthSync() {
199211

200212
try (ResultSet rs = stmt.executeQuery()) {
201213
if (rs.next()) {
202-
boolean isDegraded = performAdvancedMySQLChecksWithThrottle();
203-
return new HealthCheckResult(true, null, isDegraded);
214+
// Connection is auto-closed by try-with-resources here
215+
// Advanced checks will open a separate connection if needed
204216
}
205217
}
206218

207-
return new HealthCheckResult(false, "No result from health check query", false);
208-
209219
} catch (Exception e) {
210220
logger.warn("MySQL health check failed: {}", e.getMessage(), e);
211221
return new HealthCheckResult(false, "MySQL connection failed", false);
212222
}
223+
224+
225+
boolean isDegraded = performAdvancedMySQLChecksWithThrottle();
226+
return new HealthCheckResult(true, null, isDegraded);
213227
}
214228

215229
private HealthCheckResult checkRedisHealthSync() {
@@ -325,7 +339,7 @@ private String computeOverallStatus(Map<String, Map<String, Object>> components)
325339
}
326340

327341
private boolean performAdvancedMySQLChecksWithThrottle() {
328-
if (!ADVANCED_HEALTH_CHECKS_ENABLED) {
342+
if (!advancedHealthChecksEnabled) {
329343
return false;
330344
}
331345

0 commit comments

Comments
 (0)