feat(Tracer Bullet)
This commit is contained in:
+5
-3
@@ -1,6 +1,8 @@
|
||||
package at.mocode.infrastructure.eventstore.redis
|
||||
|
||||
import at.mocode.core.domain.event.DomainEvent
|
||||
import at.mocode.core.domain.model.AggregateId
|
||||
import at.mocode.core.domain.model.EventVersion
|
||||
import at.mocode.infrastructure.eventstore.api.ConcurrencyException
|
||||
import at.mocode.infrastructure.eventstore.api.EventSerializer
|
||||
import at.mocode.infrastructure.eventstore.api.EventStore
|
||||
@@ -26,7 +28,7 @@ class RedisEventStore(
|
||||
|
||||
val aggregateId = events.first().aggregateId
|
||||
require(events.all { it.aggregateId == aggregateId }) { "All events must belong to the same aggregate" }
|
||||
require(streamId == aggregateId) { "Stream ID must match aggregate ID" }
|
||||
require(streamId == aggregateId.value) { "Stream ID must match aggregate ID" }
|
||||
|
||||
var currentVersion = getStreamVersion(streamId)
|
||||
|
||||
@@ -59,7 +61,7 @@ class RedisEventStore(
|
||||
|
||||
private fun appendToStreamInternal(event: DomainEvent, streamId: Uuid, currentVersion: Long): Long {
|
||||
val newVersion = currentVersion + 1
|
||||
require(event.version == newVersion) { "Event version ${event.version} does not match expected new version $newVersion" }
|
||||
require(event.version.value == newVersion) { "Event version ${event.version} does not match expected new version $newVersion" }
|
||||
|
||||
val streamKey = getStreamKey(streamId)
|
||||
val allEventsStreamKey = getAllEventsStreamKey()
|
||||
@@ -102,7 +104,7 @@ class RedisEventStore(
|
||||
}
|
||||
} ?: emptyList()
|
||||
|
||||
return events.filter { it.version >= fromVersion && (toVersion == null || it.version <= toVersion) }
|
||||
return events.filter { it.version >= EventVersion(fromVersion) && (toVersion == null || it.version <= EventVersion(toVersion)) }
|
||||
}
|
||||
|
||||
override fun getStreamVersion(streamId: Uuid): Long {
|
||||
|
||||
+19
-18
@@ -2,6 +2,7 @@ package at.mocode.infrastructure.eventstore.redis
|
||||
|
||||
import at.mocode.core.domain.event.BaseDomainEvent
|
||||
import at.mocode.core.domain.event.DomainEvent
|
||||
import at.mocode.core.domain.model.*
|
||||
import at.mocode.infrastructure.eventstore.api.EventSerializer
|
||||
import at.mocode.infrastructure.eventstore.api.EventStore
|
||||
import com.benasher44.uuid.Uuid
|
||||
@@ -85,8 +86,8 @@ class RedisEventStoreIntegrationTest {
|
||||
@Test
|
||||
fun `event publishing and consuming with consumer groups should work`() {
|
||||
val aggregateId = uuid4()
|
||||
val event1 = TestCreatedEvent(aggregateId = aggregateId, version = 1L, name = "Test Entity")
|
||||
val event2 = TestUpdatedEvent(aggregateId = aggregateId, version = 2L, name = "Updated Test Entity")
|
||||
val event1 = TestCreatedEvent(aggregateId = AggregateId(aggregateId), version = EventVersion(1L), name = "Test Entity")
|
||||
val event2 = TestUpdatedEvent(aggregateId = AggregateId(aggregateId), version = EventVersion(2L), name = "Updated Test Entity")
|
||||
|
||||
val latch = CountDownLatch(2)
|
||||
val receivedEvents = mutableListOf<DomainEvent>()
|
||||
@@ -112,34 +113,34 @@ class RedisEventStoreIntegrationTest {
|
||||
|
||||
assertEquals(2, receivedEvents.size)
|
||||
|
||||
val receivedEvent1 = receivedEvents.find { it.version == 1L } as TestCreatedEvent
|
||||
assertEquals(aggregateId, receivedEvent1.aggregateId)
|
||||
val receivedEvent1 = receivedEvents.find { it.version == EventVersion(1L) } as TestCreatedEvent
|
||||
assertEquals(AggregateId(aggregateId), receivedEvent1.aggregateId)
|
||||
assertEquals("Test Entity", receivedEvent1.name)
|
||||
|
||||
val receivedEvent2 = receivedEvents.find { it.version == 2L } as TestUpdatedEvent
|
||||
assertEquals(aggregateId, receivedEvent2.aggregateId)
|
||||
val receivedEvent2 = receivedEvents.find { it.version == EventVersion(2L) } as TestUpdatedEvent
|
||||
assertEquals(AggregateId(aggregateId), receivedEvent2.aggregateId)
|
||||
assertEquals("Updated Test Entity", receivedEvent2.name)
|
||||
}
|
||||
|
||||
data class TestCreatedEvent(
|
||||
override val aggregateId: Uuid,
|
||||
override val version: Long,
|
||||
override val aggregateId: AggregateId,
|
||||
override val version: EventVersion,
|
||||
val name: String,
|
||||
override val eventType: String = "TestCreated",
|
||||
override val eventId: Uuid = uuid4(),
|
||||
override val eventType: EventType = EventType("TestCreated"),
|
||||
override val eventId: EventId = EventId(uuid4()),
|
||||
override val timestamp: Instant = Clock.System.now(),
|
||||
override val correlationId: Uuid? = null,
|
||||
override val causationId: Uuid? = null
|
||||
override val correlationId: CorrelationId? = null,
|
||||
override val causationId: CausationId? = null
|
||||
) : BaseDomainEvent(aggregateId, eventType, version, eventId, timestamp, correlationId, causationId)
|
||||
|
||||
data class TestUpdatedEvent(
|
||||
override val aggregateId: Uuid,
|
||||
override val version: Long,
|
||||
override val aggregateId: AggregateId,
|
||||
override val version: EventVersion,
|
||||
val name: String,
|
||||
override val eventType: String = "TestUpdated",
|
||||
override val eventId: Uuid = uuid4(),
|
||||
override val eventType: EventType = EventType("TestUpdated"),
|
||||
override val eventId: EventId = EventId(uuid4()),
|
||||
override val timestamp: Instant = Clock.System.now(),
|
||||
override val correlationId: Uuid? = null,
|
||||
override val causationId: Uuid? = null
|
||||
override val correlationId: CorrelationId? = null,
|
||||
override val causationId: CausationId? = null
|
||||
) : BaseDomainEvent(aggregateId, eventType, version, eventId, timestamp, correlationId, causationId)
|
||||
}
|
||||
|
||||
+13
-12
@@ -1,6 +1,7 @@
|
||||
package at.mocode.infrastructure.eventstore.redis
|
||||
|
||||
import at.mocode.core.domain.event.BaseDomainEvent
|
||||
import at.mocode.core.domain.model.*
|
||||
import at.mocode.infrastructure.eventstore.api.ConcurrencyException
|
||||
import at.mocode.infrastructure.eventstore.api.EventSerializer
|
||||
import com.benasher44.uuid.Uuid
|
||||
@@ -68,8 +69,8 @@ class RedisEventStoreTest {
|
||||
@Test
|
||||
fun `append and read events should work correctly for new stream`() {
|
||||
val aggregateId = uuid4()
|
||||
val event1 = TestCreatedEvent(aggregateId, 1L, "Test Entity")
|
||||
val event2 = TestUpdatedEvent(aggregateId, 2L, "Updated Test Entity")
|
||||
val event1 = TestCreatedEvent(AggregateId(aggregateId), EventVersion(1L), "Test Entity")
|
||||
val event2 = TestUpdatedEvent(AggregateId(aggregateId), EventVersion(2L), "Updated Test Entity")
|
||||
|
||||
eventStore.appendToStream(listOf(event1, event2), aggregateId, 0)
|
||||
|
||||
@@ -77,21 +78,21 @@ class RedisEventStoreTest {
|
||||
assertEquals(2, events.size)
|
||||
|
||||
val firstEvent = events[0] as TestCreatedEvent
|
||||
assertEquals(1L, firstEvent.version)
|
||||
assertEquals(EventVersion(1L), firstEvent.version)
|
||||
assertEquals("Test Entity", firstEvent.name)
|
||||
|
||||
val secondEvent = events[1] as TestUpdatedEvent
|
||||
assertEquals(2L, secondEvent.version)
|
||||
assertEquals(EventVersion(2L), secondEvent.version)
|
||||
assertEquals("Updated Test Entity", secondEvent.name)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `appending with wrong expected version should throw ConcurrencyException`() {
|
||||
val aggregateId = uuid4()
|
||||
val event1 = TestCreatedEvent(aggregateId, 1L, "Test Entity")
|
||||
val event1 = TestCreatedEvent(AggregateId(aggregateId), EventVersion(1L), "Test Entity")
|
||||
eventStore.appendToStream(listOf(event1), aggregateId, 0) // Stream is now at version 1
|
||||
|
||||
val event2 = TestUpdatedEvent(aggregateId, 2L, "Updated Test Entity")
|
||||
val event2 = TestUpdatedEvent(AggregateId(aggregateId), EventVersion(2L), "Updated Test Entity")
|
||||
assertThrows<ConcurrencyException> {
|
||||
eventStore.appendToStream(listOf(event2), aggregateId, 0)
|
||||
}
|
||||
@@ -99,15 +100,15 @@ class RedisEventStoreTest {
|
||||
|
||||
@Serializable
|
||||
data class TestCreatedEvent(
|
||||
@Transient override val aggregateId: Uuid = uuid4(),
|
||||
@Transient override val version: Long = 0,
|
||||
@Transient override val aggregateId: AggregateId = AggregateId(uuid4()),
|
||||
@Transient override val version: EventVersion = EventVersion(0),
|
||||
val name: String
|
||||
) : BaseDomainEvent(aggregateId, "TestCreated", version)
|
||||
) : BaseDomainEvent(aggregateId, EventType("TestCreated"), version)
|
||||
|
||||
@Serializable
|
||||
data class TestUpdatedEvent(
|
||||
@Transient override val aggregateId: Uuid = uuid4(),
|
||||
@Transient override val version: Long = 0,
|
||||
@Transient override val aggregateId: AggregateId = AggregateId(uuid4()),
|
||||
@Transient override val version: EventVersion = EventVersion(0),
|
||||
val name: String
|
||||
) : BaseDomainEvent(aggregateId, "TestUpdated", version)
|
||||
) : BaseDomainEvent(aggregateId, EventType("TestUpdated"), version)
|
||||
}
|
||||
|
||||
+13
-12
@@ -2,6 +2,7 @@ package at.mocode.infrastructure.eventstore.redis
|
||||
|
||||
import at.mocode.core.domain.event.BaseDomainEvent
|
||||
import at.mocode.core.domain.event.DomainEvent
|
||||
import at.mocode.core.domain.model.*
|
||||
import at.mocode.infrastructure.eventstore.api.EventSerializer
|
||||
import at.mocode.infrastructure.eventstore.api.EventStore
|
||||
import com.benasher44.uuid.Uuid
|
||||
@@ -78,8 +79,8 @@ class RedisIntegrationTest {
|
||||
@Test
|
||||
fun `event publishing and consuming should be fast and reliable`() {
|
||||
val aggregateId = uuid4()
|
||||
val event1 = TestCreatedEvent(aggregateId, 1L, "Test Entity")
|
||||
val event2 = TestUpdatedEvent(aggregateId, 2L, "Updated Test Entity")
|
||||
val event1 = TestCreatedEvent(AggregateId(aggregateId), EventVersion(1L), "Test Entity")
|
||||
val event2 = TestUpdatedEvent(AggregateId(aggregateId), EventVersion(2L), "Updated Test Entity")
|
||||
|
||||
val receivedEvents = mutableListOf<DomainEvent>()
|
||||
eventConsumer.registerEventHandler("TestCreated") { receivedEvents.add(it) }
|
||||
@@ -91,26 +92,26 @@ class RedisIntegrationTest {
|
||||
|
||||
assertEquals(2, receivedEvents.size)
|
||||
|
||||
val receivedEvent1 = receivedEvents.find { it.version == 1L } as TestCreatedEvent
|
||||
assertEquals(aggregateId, receivedEvent1.aggregateId)
|
||||
val receivedEvent1 = receivedEvents.find { it.version == EventVersion(1L) } as TestCreatedEvent
|
||||
assertEquals(AggregateId(aggregateId), receivedEvent1.aggregateId)
|
||||
assertEquals("Test Entity", receivedEvent1.name)
|
||||
|
||||
val receivedEvent2 = receivedEvents.find { it.version == 2L } as TestUpdatedEvent
|
||||
assertEquals(aggregateId, receivedEvent2.aggregateId)
|
||||
val receivedEvent2 = receivedEvents.find { it.version == EventVersion(2L) } as TestUpdatedEvent
|
||||
assertEquals(AggregateId(aggregateId), receivedEvent2.aggregateId)
|
||||
assertEquals("Updated Test Entity", receivedEvent2.name)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class TestCreatedEvent(
|
||||
@Transient override val aggregateId: Uuid = uuid4(),
|
||||
@Transient override val version: Long = 0,
|
||||
@Transient override val aggregateId: AggregateId = AggregateId(uuid4()),
|
||||
@Transient override val version: EventVersion = EventVersion(0),
|
||||
val name: String
|
||||
) : BaseDomainEvent(aggregateId, "TestCreated", version)
|
||||
) : BaseDomainEvent(aggregateId, EventType("TestCreated"), version)
|
||||
|
||||
@Serializable
|
||||
data class TestUpdatedEvent(
|
||||
@Transient override val aggregateId: Uuid = uuid4(),
|
||||
@Transient override val version: Long = 0,
|
||||
@Transient override val aggregateId: AggregateId = AggregateId(uuid4()),
|
||||
@Transient override val version: EventVersion = EventVersion(0),
|
||||
val name: String
|
||||
) : BaseDomainEvent(aggregateId, "TestUpdated", version)
|
||||
) : BaseDomainEvent(aggregateId, EventType("TestUpdated"), version)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user