🔊 Log exceptions that occur when running a reaction
[rhynodge.git] / src / main / java / net / pterodactylus / rhynodge / engine / Engine.java
index 7103dc5..e132b08 100644 (file)
 
 package net.pterodactylus.rhynodge.engine;
 
-import static java.lang.System.currentTimeMillis;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import jakarta.inject.Inject;
+import jakarta.inject.Singleton;
+import kotlin.Unit;
+import kotlin.jvm.functions.Function0;
+import kotlin.jvm.functions.Function1;
+import net.pterodactylus.rhynodge.Reaction;
+import net.pterodactylus.rhynodge.actions.EmailAction;
+import net.pterodactylus.rhynodge.states.StateManager;
+import org.apache.log4j.Logger;
 
 import java.util.Map;
 import java.util.Optional;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.*;
 
-import net.pterodactylus.rhynodge.Reaction;
-import net.pterodactylus.rhynodge.actions.EmailAction;
-import net.pterodactylus.rhynodge.states.StateManager;
+import static java.lang.System.currentTimeMillis;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static net.pterodactylus.util.exception.ExceptionsKt.suppressException;
 
 /**
  * Rhynodge main engine.
  *
  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
+@Singleton
 public class Engine {
 
        private final StateManager stateManager;
@@ -44,10 +48,11 @@ public class Engine {
        private final Map<String, Future<?>> scheduledFutures = new ConcurrentHashMap<>();
        private final EmailAction errorEmailAction;
 
+       @Inject
        public Engine(StateManager stateManager, EmailAction errorEmailAction) {
                this.stateManager = stateManager;
                this.errorEmailAction = errorEmailAction;
-               executorService = new ScheduledThreadPoolExecutor(10);
+               executorService = new ScheduledThreadPoolExecutor(1);
        }
 
        //
@@ -68,10 +73,24 @@ public class Engine {
                long lastExecutionTime = lastState.map(net.pterodactylus.rhynodge.State::time).orElse(0L);
                long nextExecutionTime = lastExecutionTime + reaction.updateInterval();
                ReactionRunner reactionRunner = new ReactionRunner(reaction, reactionState, errorEmailAction);
-               ScheduledFuture<?> future = executorService.scheduleWithFixedDelay(reactionRunner, nextExecutionTime - currentTimeMillis(), reaction.updateInterval(), MILLISECONDS);
+               ScheduledFuture<?> future = executorService.scheduleWithFixedDelay(suppressException(wrapRunnable(reactionRunner), logExceptionForReaction(reaction))::invoke, nextExecutionTime - currentTimeMillis(), reaction.updateInterval(), MILLISECONDS);
                scheduledFutures.put(name, future);
        }
 
+       private Function1<Exception, Unit> logExceptionForReaction(Reaction reaction) {
+               return (Exception e) -> {
+                       logger.warn("Exception during Reaction “%s”!".formatted(reaction.name()), e);
+                       return Unit.INSTANCE;
+               };
+       }
+
+       private Function0<Unit> wrapRunnable(Runnable runnable) {
+               return () -> {
+                       runnable.run();
+                       return Unit.INSTANCE;
+               };
+       }
+
        /**
         * Removes the reaction with the given name.
         *
@@ -85,4 +104,6 @@ public class Engine {
                scheduledFutures.remove(name).cancel(true);
        }
 
+       private static final Logger logger = Logger.getLogger(Engine.class);
+
 }