com.cultureamp.eventsourcing.Framework.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kestrel Show documentation
Show all versions of kestrel Show documentation
Kotlin Framework for running event-sourced services
The newest version!
package com.cultureamp.eventsourcing
import org.joda.time.DateTime
import java.util.*
import kotlin.reflect.KFunction2
import kotlin.reflect.KFunction3
import kotlin.reflect.KFunction4
import kotlin.reflect.KFunction5
interface Command {
val aggregateId: UUID
}
interface CreationCommand : Command {
override val aggregateId: UUID
}
interface UpdateCommand : Command {
override val aggregateId: UUID
}
data class Event (
val id: UUID,
val aggregateId: UUID,
val aggregateSequence: Long,
val aggregateType: String,
val createdAt: DateTime,
val metadata: M,
val domainEvent: DomainEvent
)
data class SequencedEvent(val event: Event, val sequence: Long)
open class EventMetadata
/**
* Standard Culture Amp metadata. You probably want to consider logging these fields (but note they are optional).
* If you know these fields at all times, you can probably create a new `Metadata` subclass.
*
* @property accountId: The aggregate ID of the account that owns the event’s aggregate instance
* @property executorId: The aggregate ID of the user that executed the command that resulted in the event
* @property causationId: If the event is the result of an action performed by a reactor, the ID of the causal event
* @property correlationId: The identifier of a correlated action, request or event
*/
data class CAStandardMetadata(
val accountId: UUID? = null,
val executorId: UUID? = null,
val correlationId: UUID? = null,
val causationId: UUID? = null
): EventMetadata()
interface DomainEvent
interface CreationEvent : DomainEvent
interface UpdateEvent : DomainEvent
interface CommandError
interface DomainError: CommandError
interface AlreadyActionedCommandError : DomainError
interface AuthorizationCommandError : CommandError
interface RetriableError : CommandError
sealed class Either
data class Left(val error: E) : Either()
data class Right(val value: V) : Either() {
companion object {
fun list(vararg values: V): Either> = Right(listOf(*values))
}
}
fun Either.map(transform: (V) -> R): Either = when (this) {
is Right -> Right(transform(this.value))
is Left -> this
}
fun Either>.flatten(): Either = when (this) {
is Left -> this
is Right -> this.value
}
fun Either.flatMap(transform: (V) -> Either): Either = when (this) {
is Left -> this
is Right -> transform(this.value)
}
fun Either.fold(left: (E) -> R, right: (V) -> R): R = when (this) {
is Left -> left(this.error)
is Right -> right(this.value)
}
fun KFunction2.partial(a: A): (B) -> C {
return { b -> invoke(a, b) }
}
fun ((A, B) -> C).partial(a: A): (B) -> C {
return { b -> invoke(a, b) }
}
fun KFunction3.partial(a: A): (B, C) -> D {
return { b, c -> invoke(a, b, c) }
}
fun ((A, B, C) -> D).partial(a: A): (B, C) -> D {
return { b, c -> invoke(a, b, c) }
}
fun KFunction3.partial2(b: B): (A, C) -> D {
return { a, c -> invoke(a, b, c) }
}
fun ((A, B, C) -> D).partial2(b: B): (A, C) -> D {
return { a, c -> invoke(a, b, c) }
}
fun KFunction4.partial(a: A): (B, C, D) -> E {
return { b, c, d -> invoke(a, b, c, d) }
}
fun KFunction4.partial2(b: B): (A, C, D) -> E {
return { a, c, d -> invoke(a, b, c, d) }
}
fun ((A, B, C, D) -> E).partial2(b: B): (A, C, D) -> E {
return { a, c, d -> invoke(a, b, c, d) }
}
fun KFunction5.partial2(b: B): (A, C, D, E) -> F {
return { a, c, d, e -> invoke(a, b, c, d, e) }
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy