Occurrent
Event Sourcing Utilities for the JVM
- Java
- Kotlin
public class ApplicationService {
private final EventStore eventStore;
private final Converter converter;
public ApplicationService(EventStore eventStore, Converter converter) {
this.eventStore = eventStore;
this.converter = converter;
}
public void execute(String streamId, Function<Stream<DomainEvent>, Stream<DomainEvent>> functionThatCallsDomainModel) {
// Read all events from the event store for a particular stream
EventStream<CloudEvent> eventStream = eventStore.read(streamId.toString());
// Convert the cloud events into domain events
Stream<DomainEvent> persistedDomainEvents = eventStream.events().map(converter::toDomainEvent);
// Call a pure function from the domain model which returns a Stream of domain events
Stream<DomainEvent> newDomainEvents = functionThatCallsDomainModel.apply(persistedDomainEvents);
// Convert domain events to cloud events and write them to the event store
eventStore.write(streamId, eventStream.version(), newDomainEvents.map(converter::toCloudEvent));
}
}
class ApplicationService constructor (val eventStore : EventStore, val converter : Converter) {
fun execute(streamId : String, functionThatCallsDomainModel : (Stream<DomainEvent>) -> Stream<DomainEvent>) {
// Read all events from the event store for a particular stream
val eventStream : EventStream<CloudEvent> = eventStore.read(streamId.toString())
// Convert the cloud events into domain events
val persistedDomainEvents : Stream<DomainEvent> = eventStream.events().map(converter::toDomainEvent)
// Call a pure function from the domain model which returns a Stream of domain events
val newDomainEvents = functionThatCallsDomainModel(persistedDomainEvents)
// Convert domain events to cloud events and write them to the event store
eventStore.write(streamId, eventStream.version(), newDomainEvents.map(converter::toCloudEvent))
}
}
What is Occurrent?
Unintrusive
You should be able to design your domain model without any dependencies to Occurrent or any other library. Your domain model can be expressed with pure functions that returns events. Use Occurrent to store these events.
Simple
Pick only the libraries you need, no need for an all or nothing solution.
Control
You should be in control! Magic is kept to a minimum and data is stored in a standard format (cloud events). You are responsible for serializing/deserializing the cloud events "body" (data) yourself.
Composable
Use the Occurrent components as lego bricks to compose your own pipelines. Components are designed to be small so that you should be able to re-write them tailored to your own needs if required. Write your own problem/domain specific layer on-top of Occurrent.
Library
Designed to be used as a library and not a framework to the greatest extent possible.
Pragmatic
Need consistent projections? You can decide to write projections and events transactionally using tools you already know (such as Spring @Transactional
)!
Interoperable
Cloud events is a CNCF specification for describing event data in a common way. CloudEvents seeks to dramatically simplify event declaration and delivery across services, platforms, and beyond!
Data Format
Since you know that events are stored as Cloud Events even in the database you can use the database to your advantage. For example you can create custom indexes used for fast and fully consistent domain queries directly on an event stream (or even multiple streams).