debt(pre-router): resolved most of the technical debt that was noted while finishing epic-12 and epic-13.
This commit is contained in:
@@ -5,6 +5,7 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinx_coroutines_version"
|
||||
implementation(project(":core:events"))
|
||||
implementation(project(":core:sessions"))
|
||||
implementation "org.xerial:sqlite-jdbc"
|
||||
|
||||
+7
@@ -5,6 +5,8 @@ import com.correx.core.events.events.StoredEvent
|
||||
import com.correx.core.events.stores.EventStore
|
||||
import com.correx.core.events.types.EventId
|
||||
import com.correx.core.events.types.SessionId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import java.util.concurrent.*
|
||||
import java.util.concurrent.atomic.*
|
||||
|
||||
@@ -12,6 +14,7 @@ class InMemoryEventStore : EventStore {
|
||||
private val streams = ConcurrentHashMap<SessionId, MutableList<StoredEvent>>()
|
||||
private val sequences = ConcurrentHashMap<SessionId, AtomicLong>()
|
||||
private val seenEventIds = ConcurrentHashMap.newKeySet<EventId>()
|
||||
private val subscriptions = ConcurrentHashMap<SessionId, MutableSharedFlow<StoredEvent>>()
|
||||
|
||||
override fun append(event: NewEvent): StoredEvent {
|
||||
val stream = streams.computeIfAbsent(event.metadata.sessionId) { mutableListOf() }
|
||||
@@ -52,6 +55,9 @@ class InMemoryEventStore : EventStore {
|
||||
return sequences[sessionId]?.get()
|
||||
}
|
||||
|
||||
override fun subscribe(sessionId: SessionId): Flow<StoredEvent> =
|
||||
subscriptions.computeIfAbsent(sessionId) { MutableSharedFlow(replay = 0, extraBufferCapacity = 64) }
|
||||
|
||||
private fun doAppend(event: NewEvent, stream: MutableList<StoredEvent>): StoredEvent {
|
||||
val seq = sequences.computeIfAbsent(event.metadata.sessionId) { AtomicLong(0) }
|
||||
.incrementAndGet()
|
||||
@@ -62,6 +68,7 @@ class InMemoryEventStore : EventStore {
|
||||
error("sequence violation for session ${event.metadata.sessionId}")
|
||||
}
|
||||
stream.add(stored)
|
||||
subscriptions[event.metadata.sessionId]?.tryEmit(stored)
|
||||
|
||||
return stored
|
||||
}
|
||||
|
||||
+20
-10
@@ -11,14 +11,18 @@ import com.correx.core.events.types.CorrelationId
|
||||
import com.correx.core.events.types.EventId
|
||||
import com.correx.core.events.types.SessionId
|
||||
import com.correx.infrastructure.persistence.util.JDBCHelper.transaction
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.datetime.Instant
|
||||
import java.sql.Connection
|
||||
import java.sql.ResultSet
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class SqliteEventStore(
|
||||
private val connection: Connection,
|
||||
private val jsonSerializer: JsonEventSerializer = JsonEventSerializer(eventJson)
|
||||
) : EventStore {
|
||||
private val subscriptions = ConcurrentHashMap<SessionId, MutableSharedFlow<StoredEvent>>()
|
||||
|
||||
init {
|
||||
connection.createStatement().use { stmt ->
|
||||
@@ -40,22 +44,23 @@ class SqliteEventStore(
|
||||
}
|
||||
|
||||
override fun append(event: NewEvent): StoredEvent {
|
||||
return connection.transaction {
|
||||
val stored = connection.transaction {
|
||||
val existing = findByEventId(event.metadata.eventId)
|
||||
check(existing == null) { "duplicate event_id: ${event.metadata.eventId}" }
|
||||
|
||||
val seq = nextSequence(event.metadata.sessionId)
|
||||
|
||||
val stored = StoredEvent(
|
||||
val s = StoredEvent(
|
||||
metadata = event.metadata,
|
||||
sequence = seq,
|
||||
payload = event.payload
|
||||
)
|
||||
|
||||
insert(stored)
|
||||
|
||||
stored
|
||||
insert(s)
|
||||
s
|
||||
}
|
||||
subscriptions[event.metadata.sessionId]?.tryEmit(stored)
|
||||
return stored
|
||||
}
|
||||
|
||||
override fun appendAll(events: List<NewEvent>): List<StoredEvent> {
|
||||
@@ -63,24 +68,26 @@ class SqliteEventStore(
|
||||
|
||||
val sessionId = events.first().metadata.sessionId
|
||||
|
||||
return connection.transaction {
|
||||
val stored = connection.transaction {
|
||||
events.map { event ->
|
||||
val existing = findByEventId(event.metadata.eventId)
|
||||
check(existing == null) { "duplicate event_id: ${event.metadata.eventId}" }
|
||||
|
||||
val seq = nextSequence(sessionId)
|
||||
|
||||
val stored = StoredEvent(
|
||||
val s = StoredEvent(
|
||||
metadata = event.metadata,
|
||||
sequence = seq,
|
||||
payload = event.payload
|
||||
)
|
||||
|
||||
insert(stored)
|
||||
|
||||
stored
|
||||
insert(s)
|
||||
s
|
||||
}
|
||||
}
|
||||
val flow = subscriptions[sessionId]
|
||||
if (flow != null) stored.forEach { flow.tryEmit(it) }
|
||||
return stored
|
||||
}
|
||||
|
||||
override fun read(sessionId: SessionId): List<StoredEvent> =
|
||||
@@ -139,6 +146,9 @@ class SqliteEventStore(
|
||||
}
|
||||
}
|
||||
|
||||
override fun subscribe(sessionId: SessionId): Flow<StoredEvent> =
|
||||
subscriptions.computeIfAbsent(sessionId) { MutableSharedFlow(replay = 0, extraBufferCapacity = 64) }
|
||||
|
||||
// ---------- helpers ----------
|
||||
|
||||
private fun nextSequence(sessionId: SessionId): Long =
|
||||
|
||||
Reference in New Issue
Block a user