Skip to content

tomferon/eventsourcing

Repository files navigation

eventsourcing

This is a library to do CQRS/ES in Haskell. The core library eventsourcing provides the abstractions and eventsourcing-postgresql is the adaptor for PostgreSQL. Other adaptors can be written and would be able to work together.

Key concepts

Stream

The stream is the most important concept of the library. It represents a sequence of ordered events that belongs together. In DDD (Domain-Driven Design) terminology, it corresponds to a single aggregate instance.

Stream family

Streams that share a common structure can be brought together into stream families index by some stream identifier. In DDD parlance, this would be used for aggregate types. Streams in a stream family are pretty much independent from each other in the sense that events are only ordered within streams and event identifiers can be reused between streams without conflicts.

Projection

Projections should be as easy to write and maintain as possible. This is why, with eventsourcing, the user is expected to write simple functions with a type of the following form.

event -> f a

For example, a simple aggregation function has the following type.

EventWithContext eventId metadata event -> State aggregate ()

For projections that populates SQL tables, the type would be as follows.

(streamId, EventWithContext eventId metadata event)
  -> State st [TabularDataAction] ()

These functions can then be used by the library or an adapter to be run against some stream or stream family.

By keeping these functions simple, they can easily be tested and used in different contexts. Want to switch from one adapter to another or use in-memory store for your integration tests? No problem.

Transformers

Sometimes, you want to transform some streams into other streams. You might want to migrate a stream family to get rid of obsolete streams or change the shape of some event. Maybe you want to publish events to a message broker but want to keep your internal (private) events separate from the (public) events that make their way to the broker.

Transformers are functions of the following form where inputEvent is events (with their context) coming from some stream or stream family and Transform is a monad in which you can push and merge events together to be sent downstream.

inputEvent -> Transform eventId event ()

More in-depth information

  1. Guided tutorial showcasing the core concepts.

  2. Using aggregate stores to cache aggregates instead of going through events every time.

  3. Projecting in memory from different streams into the same read model.

  4. Writing tests that are efficient.

  5. Optimistic concurrency control to write events without breaking consistency.

  6. Using TabularDataAction to write backend-agnostic projections.

  7. Migrating (and archiving) your events.

Taxonomy

This list gives an overview of the concepts and terminology used in the library:

stream

An (ordered) sequence of events belonging together forming a unit of consistency (aggregate instance in DDD.)

stream family

A family of streams indexed by some stream identifier (aggregate type in DDD.)

transformer

A function transforming a stream of events of type a into a stream of other events of type b.

aggregator

A function looping through events of a stream and accumulating an aggregate.

aggregate store

An in-memory cache containing the aggregate returned by an aggregator indexed by the stream identifier.

projection

A process going through events of a stream and doing something. More specifically, "effectful" projections can be used to project the stream of events into transactions that are sent to a database to create tables that can be queried later on.

read model

Something such as table in the database or an aggregate store that can be queried. Read models are ways to read data without having to go through all the events of a stream over and over again.

migration

A process going through all events of all streams in a stream family and migrating them — possibly compacting or deleting some of them — into a new stream family.

task manager

A process using an aggregator of tasks (with or without a start time) for all streams in a stream family and executing them when they are due.

tracking table

A table in a database used by a projection to keep track of what events have already been processed.

adaptor

An integration between eventsourcing (the core library) and a back-end such as PostgreSQL.

About

CQRS/ES library in Haskell

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages