package me.moodcat.backend; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.ScheduledThreadPoolExecutor; import lombok.extern.slf4j.Slf4j; import me.moodcat.util.CallableInUnitOfWork; import me.moodcat.util.CallableInUnitOfWork.CallableInUnitOfWorkFactory; import me.moodcat.util.DefaultLifceCycleListener; import org.eclipse.jetty.util.component.LifeCycle; import com.google.inject.Inject; import com.google.inject.Singleton; import com.google.inject.name.Named; /** * The UnitOfWorkSchedulingService can be used to schedule tasks in a * {@link com.google.inject.persist.UnitOfWork}. * Furthermore it listens on the current {@link LifeCycle} in order to terminate the threadpool on * shutdown. */ @Slf4j @Singleton public class UnitOfWorkSchedulingServiceImpl extends ScheduledThreadPoolExecutor implements UnitOfWorkSchedulingService, DefaultLifceCycleListener { private final CallableInUnitOfWork.CallableInUnitOfWorkFactory callableInUnitOfWorkFactory; @Inject public UnitOfWorkSchedulingServiceImpl( final CallableInUnitOfWorkFactory callableInUnitOfWorkFactory, @Named("thread.pool.size") final int corePoolSize, final LifeCycle lifeCycle) { super(corePoolSize); lifeCycle.addLifeCycleListener(this); this.callableInUnitOfWorkFactory = callableInUnitOfWorkFactory; } @Override public <T> Future<T> performInUnitOfWork(final Callable<T> callable) { final Callable<T> inUnitOfWork = callableInUnitOfWorkFactory.create(callable); return submit(inUnitOfWork); } @Override public Future<?> performInUnitOfWork(final Runnable runnable) { return performInUnitOfWork(() -> { runnable.run(); return null; }); } @Override public void lifeCycleStarting(final LifeCycle lifeCycle) { log.info("Instantiated {} with {} threads", getClass(), getPoolSize()); } @Override public void lifeCycleStopping(final LifeCycle lifeCycle) { log.info("Shutting down executor, waiting for {} tasks...", getActiveCount()); this.shutdown(); } }