Added signal event
This commit is contained in:
parent
f5cc32487f
commit
a9779d2371
@ -2,6 +2,7 @@ package no.iktdev.eventi.events
|
|||||||
|
|
||||||
import no.iktdev.eventi.models.DeleteEvent
|
import no.iktdev.eventi.models.DeleteEvent
|
||||||
import no.iktdev.eventi.models.Event
|
import no.iktdev.eventi.models.Event
|
||||||
|
import no.iktdev.eventi.models.SignalEvent
|
||||||
import no.iktdev.eventi.stores.EventStore
|
import no.iktdev.eventi.stores.EventStore
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ open class EventDispatcher(val eventStore: EventStore) {
|
|||||||
val derivedFromIds = events.mapNotNull { it.metadata.derivedFromId }.flatten().toSet()
|
val derivedFromIds = events.mapNotNull { it.metadata.derivedFromId }.flatten().toSet()
|
||||||
val deletedEventIds = events.filterIsInstance<DeleteEvent>().map { it.deletedEventId }
|
val deletedEventIds = events.filterIsInstance<DeleteEvent>().map { it.deletedEventId }
|
||||||
val candidates = events
|
val candidates = events
|
||||||
|
.filterNot { it is SignalEvent }
|
||||||
.filter { it.eventId !in derivedFromIds }
|
.filter { it.eventId !in derivedFromIds }
|
||||||
.filter { it.eventId !in deletedEventIds }
|
.filter { it.eventId !in deletedEventIds }
|
||||||
|
|
||||||
|
|||||||
@ -43,6 +43,6 @@ abstract class DeleteEvent(
|
|||||||
open val deletedEventId: UUID
|
open val deletedEventId: UUID
|
||||||
) : Event()
|
) : Event()
|
||||||
|
|
||||||
|
abstract class SignalEvent(): Event()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import no.iktdev.eventi.events.EventListenerRegistry
|
|||||||
import no.iktdev.eventi.events.EventTypeRegistry
|
import no.iktdev.eventi.events.EventTypeRegistry
|
||||||
import no.iktdev.eventi.models.DeleteEvent
|
import no.iktdev.eventi.models.DeleteEvent
|
||||||
import no.iktdev.eventi.models.Event
|
import no.iktdev.eventi.models.Event
|
||||||
|
import no.iktdev.eventi.models.SignalEvent
|
||||||
import no.iktdev.eventi.testUtil.wipe
|
import no.iktdev.eventi.testUtil.wipe
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
@ -19,12 +20,14 @@ import org.junit.jupiter.api.DisplayName
|
|||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@DisplayName("""
|
@DisplayName(
|
||||||
|
"""
|
||||||
EventDispatcher
|
EventDispatcher
|
||||||
Når hendelser dispatches til lyttere
|
Når hendelser dispatches til lyttere
|
||||||
Hvis hendelsene inneholder avledede, slettede eller nye events
|
Hvis hendelsene inneholder avledede, slettede eller nye events
|
||||||
Så skal dispatcheren håndtere filtrering, replays og historikk korrekt
|
Så skal dispatcheren håndtere filtrering, replays og historikk korrekt
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
class EventDispatcherTest : TestBase() {
|
class EventDispatcherTest : TestBase() {
|
||||||
|
|
||||||
val dispatcher = EventDispatcher(eventStore)
|
val dispatcher = EventDispatcher(eventStore)
|
||||||
@ -51,11 +54,13 @@ class EventDispatcherTest : TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("""
|
@DisplayName(
|
||||||
|
"""
|
||||||
Når en TriggerEvent dispatches
|
Når en TriggerEvent dispatches
|
||||||
Hvis en lytter produserer én DerivedEvent
|
Hvis en lytter produserer én DerivedEvent
|
||||||
Så skal kun én ny event produseres og prosessen stoppe
|
Så skal kun én ny event produseres og prosessen stoppe
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
fun shouldProduceOneEventAndStop() {
|
fun shouldProduceOneEventAndStop() {
|
||||||
ProducingListener()
|
ProducingListener()
|
||||||
|
|
||||||
@ -72,11 +77,13 @@ class EventDispatcherTest : TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("""
|
@DisplayName(
|
||||||
|
"""
|
||||||
Når en event allerede har avledet en DerivedEvent
|
Når en event allerede har avledet en DerivedEvent
|
||||||
Hvis dispatcheren replays historikken
|
Hvis dispatcheren replays historikken
|
||||||
Så skal ikke DerivedEvent produseres på nytt
|
Så skal ikke DerivedEvent produseres på nytt
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
fun shouldSkipAlreadyDerivedEvents() {
|
fun shouldSkipAlreadyDerivedEvents() {
|
||||||
ProducingListener()
|
ProducingListener()
|
||||||
|
|
||||||
@ -91,11 +98,13 @@ class EventDispatcherTest : TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("""
|
@DisplayName(
|
||||||
|
"""
|
||||||
Når flere events dispatches
|
Når flere events dispatches
|
||||||
Hvis en lytter mottar en event
|
Hvis en lytter mottar en event
|
||||||
Så skal hele historikken leveres i context
|
Så skal hele historikken leveres i context
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
fun shouldPassFullContextToListener() {
|
fun shouldPassFullContextToListener() {
|
||||||
val listener = ContextCapturingListener()
|
val listener = ContextCapturingListener()
|
||||||
|
|
||||||
@ -107,11 +116,13 @@ class EventDispatcherTest : TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("""
|
@DisplayName(
|
||||||
|
"""
|
||||||
Når en replay skjer
|
Når en replay skjer
|
||||||
Hvis en event allerede har produsert en DerivedEvent
|
Hvis en event allerede har produsert en DerivedEvent
|
||||||
Så skal ikke DerivedEvent produseres på nytt
|
Så skal ikke DerivedEvent produseres på nytt
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
fun shouldBehaveDeterministicallyAcrossReplays() {
|
fun shouldBehaveDeterministicallyAcrossReplays() {
|
||||||
ProducingListener()
|
ProducingListener()
|
||||||
|
|
||||||
@ -125,11 +136,13 @@ class EventDispatcherTest : TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("""
|
@DisplayName(
|
||||||
|
"""
|
||||||
Når en DeleteEvent peker på en tidligere event
|
Når en DeleteEvent peker på en tidligere event
|
||||||
Hvis dispatcheren filtrerer kandidater
|
Hvis dispatcheren filtrerer kandidater
|
||||||
Så skal slettede events ikke leveres som kandidater
|
Så skal slettede events ikke leveres som kandidater
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
fun shouldNotDeliverDeletedEventsAsCandidates() {
|
fun shouldNotDeliverDeletedEventsAsCandidates() {
|
||||||
val dispatcher = EventDispatcher(eventStore)
|
val dispatcher = EventDispatcher(eventStore)
|
||||||
val received = mutableListOf<Event>()
|
val received = mutableListOf<Event>()
|
||||||
@ -162,11 +175,13 @@ class EventDispatcherTest : TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("""
|
@DisplayName(
|
||||||
|
"""
|
||||||
Når en DeleteEvent dispatches alene
|
Når en DeleteEvent dispatches alene
|
||||||
Hvis en lytter reagerer på DeleteEvent
|
Hvis en lytter reagerer på DeleteEvent
|
||||||
Så skal DeleteEvent leveres som kandidat
|
Så skal DeleteEvent leveres som kandidat
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
fun shouldDeliverDeleteEventToListenersThatReactToIt() {
|
fun shouldDeliverDeleteEventToListenersThatReactToIt() {
|
||||||
val received = mutableListOf<Event>()
|
val received = mutableListOf<Event>()
|
||||||
object : EventListener() {
|
object : EventListener() {
|
||||||
@ -183,11 +198,13 @@ class EventDispatcherTest : TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("""
|
@DisplayName(
|
||||||
|
"""
|
||||||
Når en event har avledet en ny event
|
Når en event har avledet en ny event
|
||||||
Hvis dispatcheren replays historikken
|
Hvis dispatcheren replays historikken
|
||||||
Så skal ikke original-eventen leveres som kandidat igjen
|
Så skal ikke original-eventen leveres som kandidat igjen
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
fun shouldNotRedeliverEventsThatHaveProducedDerivedEvents() {
|
fun shouldNotRedeliverEventsThatHaveProducedDerivedEvents() {
|
||||||
ProducingListener()
|
ProducingListener()
|
||||||
|
|
||||||
@ -211,11 +228,13 @@ class EventDispatcherTest : TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("""
|
@DisplayName(
|
||||||
|
"""
|
||||||
Når en DeleteEvent slettet en tidligere event
|
Når en DeleteEvent slettet en tidligere event
|
||||||
Hvis dispatcheren bygger historikk
|
Hvis dispatcheren bygger historikk
|
||||||
Så skal slettede events ikke være med i history
|
Så skal slettede events ikke være med i history
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
fun historyShouldExcludeDeletedEvents() {
|
fun historyShouldExcludeDeletedEvents() {
|
||||||
val dispatcher = EventDispatcher(eventStore)
|
val dispatcher = EventDispatcher(eventStore)
|
||||||
|
|
||||||
@ -238,11 +257,13 @@ class EventDispatcherTest : TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("""
|
@DisplayName(
|
||||||
|
"""
|
||||||
Når en DeleteEvent slettet en event
|
Når en DeleteEvent slettet en event
|
||||||
Hvis andre events fortsatt er gyldige
|
Hvis andre events fortsatt er gyldige
|
||||||
Så skal history kun inneholde de ikke-slettede events
|
Så skal history kun inneholde de ikke-slettede events
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
fun historyShouldKeepNonDeletedEvents() {
|
fun historyShouldKeepNonDeletedEvents() {
|
||||||
val dispatcher = EventDispatcher(eventStore)
|
val dispatcher = EventDispatcher(eventStore)
|
||||||
|
|
||||||
@ -267,11 +288,13 @@ class EventDispatcherTest : TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("""
|
@DisplayName(
|
||||||
|
"""
|
||||||
Når en DeleteEvent er kandidat
|
Når en DeleteEvent er kandidat
|
||||||
Hvis historikken kun inneholder slettede events
|
Hvis historikken kun inneholder slettede events
|
||||||
Så skal history være tom
|
Så skal history være tom
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
fun deleteEventShouldBeDeliveredButHistoryEmpty() {
|
fun deleteEventShouldBeDeliveredButHistoryEmpty() {
|
||||||
val dispatcher = EventDispatcher(eventStore)
|
val dispatcher = EventDispatcher(eventStore)
|
||||||
|
|
||||||
@ -295,6 +318,54 @@ class EventDispatcherTest : TestBase() {
|
|||||||
assertTrue(receivedHistory.isEmpty())
|
assertTrue(receivedHistory.isEmpty())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"""
|
||||||
|
Når en SignalEvent dispatches
|
||||||
|
Hvis SignalEvent ikke skal være kandidat
|
||||||
|
Så skal den ikke leveres til lyttere, men fortsatt være i historikken
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun shouldNotDeliverSignalEventAsCandidate() {
|
||||||
|
// Arrange
|
||||||
|
class TestSignalEvent : SignalEvent()
|
||||||
|
EventTypeRegistry.register(listOf(TestSignalEvent::class.java,))
|
||||||
|
|
||||||
|
val received = mutableListOf<Event>()
|
||||||
|
var finalHistory: List<Event>? = null
|
||||||
|
object : EventListener() {
|
||||||
|
override fun onEvent(event: Event, history: List<Event>): Event? {
|
||||||
|
received += event
|
||||||
|
finalHistory = history
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val refId = UUID.randomUUID()
|
||||||
|
val trigger = TriggerEvent().usingReferenceId(refId)
|
||||||
|
val signal = TestSignalEvent().usingReferenceId(refId)
|
||||||
|
|
||||||
|
// Act
|
||||||
|
dispatcher.dispatch(trigger.referenceId, listOf(trigger, signal))
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
// 1) TriggerEvent skal leveres
|
||||||
|
assertTrue(received.any { it is TriggerEvent }) {
|
||||||
|
"TriggerEvent skal leveres som kandidat"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) SignalEvent skal IKKE leveres
|
||||||
|
assertFalse(received.any { it is TestSignalEvent }) {
|
||||||
|
"SignalEvent skal ikke leveres som kandidat"
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull(finalHistory)
|
||||||
|
assertTrue(finalHistory!!.any { it is TestSignalEvent }) {
|
||||||
|
"SignalEvent skal være i historikken selv om den ikke er kandidat"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// --- Test helpers ---
|
// --- Test helpers ---
|
||||||
|
|
||||||
class ProducingListener : EventListener() {
|
class ProducingListener : EventListener() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user