feat(module): Introduce ModuleExecutor and ModuleExecutorImpl for task execution management

This commit is contained in:
extio-de
2025-12-22 20:23:48 +01:00
parent 1e4ebb08a4
commit a971033d97
6 changed files with 207 additions and 7 deletions

View File

@@ -31,11 +31,11 @@ public abstract class AbstractClientModule extends AbstractModule {
}
public void runUiPreEvents() {
public void runUiPre() {
}
public void runUiPostEvents() {
public void runUiPost() {
}

View File

@@ -0,0 +1,7 @@
package de.extio.game_engine.module;
public interface ModuleExecutor {
void execute();
}

View File

@@ -0,0 +1,62 @@
package de.extio.game_engine.module;
import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.StructuredTaskScope.Joiner;
import java.util.function.Consumer;
import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ModuleExecutorImpl implements ModuleExecutor {
private static final Logger LOGGER = LoggerFactory.getLogger(ModuleExecutorImpl.class);
private final ModuleManager moduleManager;
public ModuleExecutorImpl(final ModuleManager moduleManager) {
this.moduleManager = moduleManager;
}
@Override
public void execute() {
this.runTasks(module -> () -> {
if (module instanceof final AbstractClientModule clientModule && this.moduleManager.getModulesDisplayedClientModules().contains(clientModule)) {
this.invokeSafe(clientModule, AbstractClientModule::runUiPre);
}
});
this.runTasks(module -> () -> {
this.invokeSafe(module, AbstractModule::run);
});
this.runTasks(module -> () -> {
if (module instanceof final AbstractClientModule clientModule && this.moduleManager.getModulesDisplayedClientModules().contains(clientModule)) {
this.invokeSafe(clientModule, AbstractClientModule::runUiPost);
}
});
}
private <T extends AbstractModule> void invokeSafe(final T module, final Consumer<T> consumer) {
try {
consumer.accept(module);
}
catch (final Exception exc) {
LOGGER.error("Error in module " + module.getClass().getName(), exc);
}
}
private void runTasks(final Function<AbstractModule, Runnable> taskSupplier) {
try (var scope = StructuredTaskScope.open(Joiner.awaitAll())) {
for (final var module : this.moduleManager.getModulesActive()) {
final var task = taskSupplier.apply(module);
if (task != null) {
scope.fork(task);
}
}
scope.join();
}
catch (final InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}

View File

@@ -10,11 +10,17 @@ import org.springframework.context.annotation.Bean;
@AutoConfiguration
@ConditionalOnProperty(name = "game-engine.module.enabled", havingValue = "true", matchIfMissing = true)
public class ModuleManagerAutoConfiguration {
@Bean
@ConditionalOnMissingBean
ModuleManager moduleManager(final List<AbstractModule> initialModules) {
return new ModuleManagerImpl(initialModules);
}
@Bean
@ConditionalOnMissingBean
ModuleExecutor moduleExecutor(final ModuleManager moduleManager) {
return new ModuleExecutorImpl(moduleManager);
}
}

View File

@@ -6,13 +6,13 @@ import java.util.Deque;
import java.util.List;
import java.util.function.Consumer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
public class ModuleManagerImpl implements InitializingBean, ModuleManager {
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LoggerFactory.getLogger(ModuleManagerImpl.class);
private final List<AbstractModule> modulesInitial;