diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/SyncAsyncExecutor.java b/scm-core/src/main/java/sonia/scm/repository/spi/SyncAsyncExecutor.java index 86d37814da..8ba7af3155 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/SyncAsyncExecutor.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/SyncAsyncExecutor.java @@ -1,43 +1,16 @@ package sonia.scm.repository.spi; -import java.time.Instant; -import java.util.concurrent.Executor; import java.util.function.Consumer; -import static sonia.scm.repository.spi.SyncAsyncExecutor.ExecutionType.ASYNCHRONOUS; -import static sonia.scm.repository.spi.SyncAsyncExecutor.ExecutionType.SYNCHRONOUS; +public interface SyncAsyncExecutor { -public class SyncAsyncExecutor { + ExecutionType execute(Runnable runnable); - private final Executor executor; - private final Instant switchToAsyncTime; - private boolean executedAllSynchronously = true; + ExecutionType execute(Consumer runnable); - SyncAsyncExecutor(Executor executor, Instant switchToAsyncTime) { - this.executor = executor; - this.switchToAsyncTime = switchToAsyncTime; - } + boolean hasExecutedAllSynchronously(); - public ExecutionType execute(Runnable runnable) { - return execute(ignored -> runnable.run()); - } - - public ExecutionType execute(Consumer runnable) { - if (Instant.now().isAfter(switchToAsyncTime)) { - executor.execute(() -> runnable.accept(ASYNCHRONOUS)); - executedAllSynchronously = false; - return ASYNCHRONOUS; - } else { - runnable.accept(SYNCHRONOUS); - return SYNCHRONOUS; - } - } - - public boolean hasExecutedAllSynchronously() { - return executedAllSynchronously; - } - - public enum ExecutionType { + enum ExecutionType { SYNCHRONOUS, ASYNCHRONOUS } } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/SyncAsyncExecutorProvider.java b/scm-core/src/main/java/sonia/scm/repository/spi/SyncAsyncExecutorProvider.java index 2c576f814f..2d21129eb2 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/SyncAsyncExecutorProvider.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/SyncAsyncExecutorProvider.java @@ -1,29 +1,12 @@ package sonia.scm.repository.spi; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; +public interface SyncAsyncExecutorProvider { -public class SyncAsyncExecutorProvider { + int DEFAULT_TIMEOUT_SECONDS = 2; - private static final int DEFAULT_TIMEOUT_SECONDS = 2; - - private final Executor executor; - - public SyncAsyncExecutorProvider() { - this(Executors.newFixedThreadPool(4)); - } - - public SyncAsyncExecutorProvider(Executor executor) { - this.executor = executor; - } - - public SyncAsyncExecutor createExecutorWithDefaultTimeout() { + default SyncAsyncExecutor createExecutorWithDefaultTimeout() { return createExecutorWithSecondsToTimeout(DEFAULT_TIMEOUT_SECONDS); } - public SyncAsyncExecutor createExecutorWithSecondsToTimeout(int seconds) { - return new SyncAsyncExecutor(executor, Instant.now().plus(seconds, ChronoUnit.SECONDS)); - } + SyncAsyncExecutor createExecutorWithSecondsToTimeout(int seconds); } diff --git a/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ApplicationModuleProvider.java b/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ApplicationModuleProvider.java index 62793da0f6..d5ccb73c7d 100644 --- a/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ApplicationModuleProvider.java +++ b/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ApplicationModuleProvider.java @@ -12,6 +12,7 @@ import sonia.scm.debug.DebugModule; import sonia.scm.filter.WebElementModule; import sonia.scm.plugin.ExtensionProcessor; import sonia.scm.plugin.PluginLoader; +import sonia.scm.repository.ExecutorModule; import javax.servlet.ServletContext; import java.util.ArrayList; @@ -51,6 +52,7 @@ public class ApplicationModuleProvider implements ModuleProvider { moduleList.add(new DebugModule()); } moduleList.add(new MapperModule()); + moduleList.add(new ExecutorModule()); return moduleList; } diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultSyncAsyncExecutor.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultSyncAsyncExecutor.java new file mode 100644 index 0000000000..232435aec5 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultSyncAsyncExecutor.java @@ -0,0 +1,41 @@ +package sonia.scm.repository; + +import sonia.scm.repository.spi.SyncAsyncExecutor; + +import java.time.Instant; +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +import static sonia.scm.repository.spi.SyncAsyncExecutor.ExecutionType.ASYNCHRONOUS; +import static sonia.scm.repository.spi.SyncAsyncExecutor.ExecutionType.SYNCHRONOUS; + +public class DefaultSyncAsyncExecutor implements SyncAsyncExecutor { + + private final Executor executor; + private final Instant switchToAsyncTime; + private boolean executedAllSynchronously = true; + + DefaultSyncAsyncExecutor(Executor executor, Instant switchToAsyncTime) { + this.executor = executor; + this.switchToAsyncTime = switchToAsyncTime; + } + + public ExecutionType execute(Runnable runnable) { + return execute(ignored -> runnable.run()); + } + + public ExecutionType execute(Consumer runnable) { + if (Instant.now().isAfter(switchToAsyncTime)) { + executor.execute(() -> runnable.accept(ASYNCHRONOUS)); + executedAllSynchronously = false; + return ASYNCHRONOUS; + } else { + runnable.accept(SYNCHRONOUS); + return SYNCHRONOUS; + } + } + + public boolean hasExecutedAllSynchronously() { + return executedAllSynchronously; + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultSyncAsyncExecutorProvider.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultSyncAsyncExecutorProvider.java new file mode 100644 index 0000000000..0be7d38234 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultSyncAsyncExecutorProvider.java @@ -0,0 +1,32 @@ +package sonia.scm.repository; + +import sonia.scm.repository.spi.SyncAsyncExecutor; +import sonia.scm.repository.spi.SyncAsyncExecutorProvider; + +import java.io.Closeable; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class DefaultSyncAsyncExecutorProvider implements SyncAsyncExecutorProvider, Closeable { + + private final ExecutorService executor; + + public DefaultSyncAsyncExecutorProvider() { + this(Executors.newFixedThreadPool(4)); + } + + public DefaultSyncAsyncExecutorProvider(ExecutorService executor) { + this.executor = executor; + } + + public SyncAsyncExecutor createExecutorWithSecondsToTimeout(int seconds) { + return new DefaultSyncAsyncExecutor(executor, Instant.now().plus(seconds, ChronoUnit.SECONDS)); + } + + @Override + public void close() { + executor.shutdownNow(); + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/repository/ExecutorModule.java b/scm-webapp/src/main/java/sonia/scm/repository/ExecutorModule.java new file mode 100644 index 0000000000..4e494b6ba6 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/repository/ExecutorModule.java @@ -0,0 +1,12 @@ +package sonia.scm.repository; + +import com.google.inject.AbstractModule; +import sonia.scm.lifecycle.modules.CloseableModule; +import sonia.scm.repository.spi.SyncAsyncExecutorProvider; + +public class ExecutorModule extends AbstractModule { + @Override + protected void configure() { + bind(SyncAsyncExecutorProvider.class).to(DefaultSyncAsyncExecutorProvider.class); + } +}