package com.constellio.data.threads; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import com.constellio.data.conf.DataLayerConfiguration; import com.constellio.data.dao.managers.StatefulService; import com.constellio.data.dao.services.factories.DataLayerFactory; import com.constellio.data.threads.BackgroundThreadsManagerRuntimeException.BackgroundThreadsManagerRuntimeException_ManagerMustBeStartedBeforeConfiguringThreads; import com.constellio.data.threads.BackgroundThreadsManagerRuntimeException.BackgroundThreadsManagerRuntimeException_RepeatInfosNotConfigured; public class BackgroundThreadsManager implements StatefulService { AtomicBoolean systemStarted = new AtomicBoolean(false); AtomicBoolean stopRequested = new AtomicBoolean(false); DataLayerConfiguration dataLayerConfiguration; ScheduledExecutorService scheduledExecutorService; Semaphore tasksSemaphore; DataLayerFactory dataLayerFactory; public BackgroundThreadsManager(DataLayerConfiguration dataLayerConfiguration, DataLayerFactory dataLayerFactory) { this.dataLayerConfiguration = dataLayerConfiguration; this.tasksSemaphore = new Semaphore(1000); this.dataLayerFactory = dataLayerFactory; } @Override public void initialize() { this.scheduledExecutorService = newScheduledExecutorService(); } @Override public void close() { stopRequested.set(true); if (scheduledExecutorService != null) { scheduledExecutorService.shutdown(); try { scheduledExecutorService.awaitTermination(1, TimeUnit.HOURS); } catch (InterruptedException e) { throw new RuntimeException(e); } } try { tasksSemaphore.acquire(1000); tasksSemaphore.release(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } public void onSystemStarted() { systemStarted.set(true); } public void configure(BackgroundThreadConfiguration backgroundThreadConfiguration) { if (scheduledExecutorService == null) { throw new BackgroundThreadsManagerRuntimeException_ManagerMustBeStartedBeforeConfiguringThreads(); } if (backgroundThreadConfiguration.getExecuteEvery() == null) { throw new BackgroundThreadsManagerRuntimeException_RepeatInfosNotConfigured(); } Runnable command = getRunnableCommand(backgroundThreadConfiguration); long delayBeforeTheFirstCommandExecution = 0; long executeEverySeconds = backgroundThreadConfiguration.getExecuteEvery().getStandardSeconds(); TimeUnit unit = TimeUnit.SECONDS; if (dataLayerConfiguration.isBackgroundThreadsEnabled()) { scheduledExecutorService.scheduleAtFixedRate(command, delayBeforeTheFirstCommandExecution, executeEverySeconds, unit); } } Runnable getRunnableCommand(BackgroundThreadConfiguration backgroundThreadConfiguration) { return new BackgroundThreadCommand(backgroundThreadConfiguration, systemStarted, stopRequested, tasksSemaphore, dataLayerFactory); } ScheduledExecutorService newScheduledExecutorService() { return Executors.newScheduledThreadPool(4 * dataLayerConfiguration.getBackgroudThreadsPoolSize()); } }