package com.constellio.data.threads; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicBoolean; import org.joda.time.LocalTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.constellio.data.dao.services.factories.DataLayerFactory; import com.constellio.data.utils.TimeProvider; public class BackgroundThreadCommand implements Runnable { BackgroundThreadConfiguration configuration; Logger logger; String threadName; AtomicBoolean stopRequested; AtomicBoolean systemStarted; Semaphore tasksSemaphore; public BackgroundThreadCommand(BackgroundThreadConfiguration configuration, AtomicBoolean systemStarted, AtomicBoolean stopRequested, Semaphore tasksSemaphore, DataLayerFactory dataLayerFactory) { this.configuration = configuration; this.tasksSemaphore = tasksSemaphore; this.logger = LoggerFactory.getLogger(configuration.getRepeatedAction().getClass()); this.threadName = dataLayerFactory .toResourceName(configuration.getId() + " (" + configuration.getRepeatedAction().getClass().getName() + ")"); this.stopRequested = stopRequested; this.systemStarted = systemStarted; } @Override public void run() { while (!systemStarted.get() && !stopRequested.get()) { try { Thread.sleep(50); } catch (InterruptedException e) { throw new RuntimeException(e); } } if ((configuration.getFrom() == null || configuration.getTo() == null || isBetweenInterval()) && !stopRequested.get()) { try { tasksSemaphore.acquire(); } catch (InterruptedException e) { throw new RuntimeException(e); } try { runAndHandleException(); } finally { tasksSemaphore.release(); } } } private boolean isBetweenInterval() { LocalTime localTime = TimeProvider.getLocalDateTime().toLocalTime(); if (configuration.getFrom().isBefore(configuration.getTo())) { return localTime.isAfter(configuration.getFrom()) && localTime.isBefore(configuration.getTo()); } else { return localTime.isAfter(configuration.getFrom()) || localTime.isBefore(configuration.getTo()); } } public void runAndHandleException() { setCurrentThreadName(); //logCommandCall(); try { configuration.getRepeatedAction().run(); //logCommandCallEnd(); } catch (Throwable e) { logCommandCallEndedWithException(e); if (configuration.getExceptionHandling() == BackgroundThreadExceptionHandling.STOP) { throw e; } } } public void setCurrentThreadName() { Thread.currentThread().setName(threadName); } public void logCommandCall() { logger.info("Executing background thread " + threadName); } public void logCommandCallEnd() { logger.info("Execution of background thread " + threadName + "' ended normally"); } public void logCommandCallEndedWithException(Throwable e) { logger.error("Execution of background thread " + threadName + "' has thrown an exception", e); } }