X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Frhynodge%2Fengine%2FReactionRunner.java;h=45642cebc6c696b545540cb271bbded6552feb5b;hb=8aeef90590095a455e2323d70ba8ccae032f4276;hp=37bec1071bc4f65715e31c57db359a4ac265ea13;hpb=09c47ffd3d61d5d8d63e95d253318ec361433c76;p=rhynodge.git
diff --git a/src/main/java/net/pterodactylus/rhynodge/engine/ReactionRunner.java b/src/main/java/net/pterodactylus/rhynodge/engine/ReactionRunner.java
index 37bec10..45642ce 100644
--- a/src/main/java/net/pterodactylus/rhynodge/engine/ReactionRunner.java
+++ b/src/main/java/net/pterodactylus/rhynodge/engine/ReactionRunner.java
@@ -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;
@@ -12,14 +15,17 @@ import net.pterodactylus.rhynodge.Filter;
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.Merger;
+import net.pterodactylus.rhynodge.output.DefaultOutput;
+import net.pterodactylus.rhynodge.output.Output;
import net.pterodactylus.rhynodge.states.FailedState;
import org.apache.log4j.Logger;
/**
* Runs a {@link Reaction}, starting with its {@link Query}, running the {@link
- * State} through its {@link Filter}s, and finally checking the {@link Trigger}
+ * State} through its {@link Filter}s, and finally checking the {@link Merger}
* for whether an {@link Action} needs to be executed.
*
* @author David âBombeâ Roden
@@ -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,12 @@ 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));
+ Optional lastState = reactionState.loadLastState();
saveStateWithIncreasedFailCount(state);
+ if (thisFailureIsTheFirstFailure(lastState)) {
+ errorEmailAction.execute(createErrorOutput(reaction, state));
+ }
return;
}
Optional lastSuccessfulState = reactionState.loadLastSuccessfulState();
@@ -50,22 +62,53 @@ public class ReactionRunner implements Runnable {
reactionState.saveState(state);
return;
}
- Trigger trigger = reaction.trigger();
- State newState = trigger.mergeStates(lastSuccessfulState.get(), state);
+ Merger merger = reaction.merger();
+ State newState = merger.mergeStates(lastSuccessfulState.get(), state);
reactionState.saveState(newState);
- if (trigger.triggers()) {
+ if (newState.triggered()) {
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()));
}
+ private static boolean thisFailureIsTheFirstFailure(Optional lastState) {
+ return lastState.map(State::success).orElse(true);
+ }
+
private void saveStateWithIncreasedFailCount(State state) {
Optional lastState = reactionState.loadLastState();
state.setFailCount(lastState.map(State::failCount).orElse(0) + 1);
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 {
@@ -85,6 +128,7 @@ public class ReactionRunner implements Runnable {
currentState = filter.filter(currentState);
} catch (Throwable t1) {
logger.warn(format("Error during filter %s for %s.", filter.getClass().getSimpleName(), reaction.name()), t1);
+ return new FailedState(t1);
}
}
}