♻️ Move output generation to state
[rhynodge.git] / src / main / java / net / pterodactylus / rhynodge / engine / ReactionRunner.java
index ac25e18..a4006d8 100644 (file)
@@ -5,6 +5,9 @@ import static java.util.Optional.ofNullable;
 import static net.pterodactylus.rhynodge.states.FailedState.INSTANCE;
 import static org.apache.log4j.Logger.getLogger;
 
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.Optional;
 
 import net.pterodactylus.rhynodge.Action;
@@ -13,6 +16,9 @@ import net.pterodactylus.rhynodge.Query;
 import net.pterodactylus.rhynodge.Reaction;
 import net.pterodactylus.rhynodge.State;
 import net.pterodactylus.rhynodge.Trigger;
+import net.pterodactylus.rhynodge.actions.EmailAction;
+import net.pterodactylus.rhynodge.output.DefaultOutput;
+import net.pterodactylus.rhynodge.output.Output;
 import net.pterodactylus.rhynodge.states.FailedState;
 
 import org.apache.log4j.Logger;
@@ -29,10 +35,12 @@ public class ReactionRunner implements Runnable {
        private static final Logger logger = getLogger(ReactionRunner.class);
        private final Reaction reaction;
        private final ReactionState reactionState;
+       private final EmailAction errorEmailAction;
 
-       public ReactionRunner(Reaction reaction, ReactionState reactionState) {
+       public ReactionRunner(Reaction reaction, ReactionState reactionState, EmailAction errorEmailAction) {
                this.reactionState = reactionState;
                this.reaction = reaction;
+               this.errorEmailAction = errorEmailAction;
        }
 
        @Override
@@ -40,8 +48,9 @@ public class ReactionRunner implements Runnable {
                State state = runQuery();
                state = runStateThroughFilters(state);
                if (!state.success()) {
-                       logger.info(format("Reaction %s failed.", reaction.name()));
+                       logger.info(format("Reaction %s failed in %s.", reaction.name(), state));
                        saveStateWithIncreasedFailCount(state);
+                       errorEmailAction.execute(createErrorOutput(reaction, state));
                        return;
                }
                Optional<State> lastSuccessfulState = reactionState.loadLastSuccessfulState();
@@ -55,7 +64,7 @@ public class ReactionRunner implements Runnable {
                reactionState.saveState(newState);
                if (trigger.triggers()) {
                        logger.info(format("Trigger was hit for %s, executing action...", reaction.name()));
-                       reaction.action().execute(trigger.output(reaction));
+                       reaction.action().execute(newState.output(reaction));
                }
                logger.info(format("Reaction %s finished.", reaction.name()));
        }
@@ -66,6 +75,33 @@ public class ReactionRunner implements Runnable {
                reactionState.saveState(state);
        }
 
+       private Output createErrorOutput(Reaction reaction, State state) {
+               DefaultOutput output = new DefaultOutput(String.format("Error while processing “%s!”", reaction.name()));
+               output.addText("text/plain", createErrorEmailText(reaction, state));
+               output.addText("text/html", createErrorEmailText(reaction, state));
+               return output;
+       }
+
+       private String createErrorEmailText(Reaction reaction, State state) {
+               StringBuilder emailText = new StringBuilder();
+               emailText.append(String.format("An error occured while processing “%s.”\n\n", reaction.name()));
+               appendExceptionToEmailText(state.exception(), emailText);
+               return emailText.toString();
+       }
+
+       private void appendExceptionToEmailText(Throwable exception, StringBuilder emailText) {
+               if (exception != null) {
+                       try (StringWriter stringWriter = new StringWriter();
+                                PrintWriter printWriter = new PrintWriter(stringWriter)) {
+                               exception.printStackTrace(printWriter);
+                               emailText.append(stringWriter.toString());
+                       } catch (IOException ioe1) {
+                               /* StringWriter doesn’t throw. */
+                               throw new RuntimeException(ioe1);
+                       }
+               }
+       }
+
        private State runQuery() {
                logger.info(format("Querying %s...", reaction.name()));
                try {