diff --git a/src/main/java/org/springframework/samples/petclinic/errors/MonitorService.java b/src/main/java/org/springframework/samples/petclinic/errors/MonitorService.java index af0ad68a219..6cdcd332242 100644 --- a/src/main/java/org/springframework/samples/petclinic/errors/MonitorService.java +++ b/src/main/java/org/springframework/samples/petclinic/errors/MonitorService.java @@ -8,70 +8,111 @@ import org.springframework.stereotype.Component; import java.util.InvalidPropertiesFormatException; +import java.util.concurrent.atomic.AtomicInteger; @Component public class MonitorService implements SmartLifecycle { - private boolean running = false; - private Thread backgroundThread; - @Autowired - private OpenTelemetry openTelemetry; - - @Override - public void start() { - var otelTracer = openTelemetry.getTracer("MonitorService"); - - running = true; - backgroundThread = new Thread(() -> { - while (running) { - - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - Span span = otelTracer.spanBuilder("monitor").startSpan(); - - try { - - System.out.println("Background service is running..."); - monitor(); - } catch (Exception e) { - span.recordException(e); - span.setStatus(StatusCode.ERROR); - } finally { - span.end(); - } - } - }); - - // Start the background thread - backgroundThread.start(); - System.out.println("Background service started."); - } - - private void monitor() throws InvalidPropertiesFormatException { - Utils.throwException(IllegalStateException.class,"monitor failure"); - } - - - - @Override - public void stop() { - // Stop the background task - running = false; - if (backgroundThread != null) { - try { - backgroundThread.join(); // Wait for the thread to finish - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - System.out.println("Background service stopped."); - } - - @Override - public boolean isRunning() { - return false; - } -} + public enum SystemStatus { + STARTING, + RUNNING, + STOPPING, + STOPPED, + ERROR + } + + private volatile SystemStatus currentStatus = SystemStatus.STOPPED; + private volatile boolean running = false; + private Thread backgroundThread; + private final AtomicInteger retryCount = new AtomicInteger(0); + private final int MAX_RETRIES = 3; + private final long RETRY_DELAY_MS = 1000; + private volatile Exception lastError; + + @Autowired + private OpenTelemetry openTelemetry; + + @Override + public void start() { + var otelTracer = openTelemetry.getTracer("MonitorService"); + currentStatus = SystemStatus.STARTING; + running = true; + retryCount.set(0); + lastError = null; + + backgroundThread = new Thread(() -> { + while (running) { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + + Span span = otelTracer.spanBuilder("monitor").startSpan(); + try { + currentStatus = SystemStatus.RUNNING; + monitor(); + retryCount.set(0); + } catch (Exception e) { + lastError = e; + span.recordException(e); + span.setStatus(StatusCode.ERROR); + currentStatus = SystemStatus.ERROR; + + if (retryCount.incrementAndGet() <= MAX_RETRIES) { + try { + Thread.sleep(RETRY_DELAY_MS * retryCount.get()); + continue; + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + break; + } + } + } finally { + span.end(); + } + } + }); + + backgroundThread.start(); + System.out.println("Background service started."); + } + + private void monitor() throws InvalidPropertiesFormatException { + try { + Utils.throwException(IllegalStateException.class, "monitor failure"); + } catch (Exception e) { + throw new InvalidPropertiesFormatException("Monitor operation failed: " + e.getMessage()); + } + } + + @Override + public void stop() { + currentStatus = SystemStatus.STOPPING; + running = false; + if (backgroundThread != null) { + backgroundThread.interrupt(); + try { + backgroundThread.join(5000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + currentStatus = SystemStatus.STOPPED; + System.out.println("Background service stopped."); + } + + @Override + public boolean isRunning() { + return running && currentStatus == SystemStatus.RUNNING; + } + + public SystemStatus getCurrentStatus() { + return currentStatus; + } + + public Exception getLastError() { + return lastError; + } +} \ No newline at end of file