✨ Always send email when first state arrives
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Mon, 20 Apr 2026 15:52:47 +0000 (17:52 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Mon, 20 Apr 2026 15:52:47 +0000 (17:52 +0200)
src/main/java/net/pterodactylus/rhynodge/engine/ReactionRunner.java
src/test/kotlin/net/pterodactylus/rhynodge/engine/ReactionRunnerTest.kt

index bff7a33..a2cc0c4 100644 (file)
@@ -58,6 +58,7 @@ public class ReactionRunner implements Runnable {
                if (!lastSuccessfulState.isPresent()) {
                        logger.info(format("No last state for %s.", reaction.name()));
                        reactionState.saveState(state);
+                       reaction.action().execute(state.output(reaction));
                        return;
                }
                Merger merger = reaction.merger();
index c68278e..50ecb22 100644 (file)
@@ -20,6 +20,7 @@ import java.util.Optional.empty
 import java.util.Optional.of
 import java.util.concurrent.atomic.AtomicBoolean
 import java.util.concurrent.atomic.AtomicReference
+import net.pterodactylus.rhynodge.Action
 import org.mockito.Mockito.mock
 
 /**
@@ -71,6 +72,16 @@ class ReactionRunnerTest {
        }
 
        @Test
+       fun `reaction runner triggers mail when last state does not exist and current state is successful`() {
+               val reactionState = createReactionState()
+               val emailSent = AtomicReference<String>()
+               val reaction = createReaction { emailSent.set(it.text("text/plain")) }
+               val reactionRunner = ReactionRunner(reaction, reactionState, nullEmailAction)
+               reactionRunner.run()
+               assertThat(emailSent.get(), equalTo("Test Output"))
+       }
+
+       @Test
        fun `reaction runner saves state when unsuccessful and last state is failed`() {
                val savedState = AtomicReference<State>()
                val failedState = FailedState().apply { setFailCount(12) }
@@ -91,6 +102,14 @@ class ReactionRunnerTest {
                override fun execute(output: Output) = action()
        }
 
+       private fun createReaction(action: (output: Output) -> Unit = {}) = object : Reaction("Test", mock(), mock(), Action { output, _ -> action(output) }) {
+               override fun query() = Query {
+                       object : AbstractState(true, false) {
+                               override fun plainText() = "Test Output"
+                       }
+               }
+       }
+
        private val reactionState = createReactionState()
        private val failingReaction = object : Reaction("Test", mock(), mock(), mock()) {
                override fun query() = Query { FailedState() }