An event sourcing library for Clojure on top of SQL, for SQLite and PostgreSQL.
Commands, events, and read-model projections commit in one database
transaction. Projections are never stale, and they can enforce invariants
that commands rely on, like a unique username. Effects that must leave the
database (email, message queues, HTTP calls) go through a transactional
outbox: delivered after commit, in order, at least once. There is no
aggregate framework and no eventual-consistency machinery. You write decide
and evolve as plain functions; Okazi owns the transaction boundary and the
outbox delivery.
Planned shape:
(require '[okazi.core :as okz])
(def store (okz/store datasource {:projections [usernames] :listeners [emailer]}))
(okz/init! store)
(okz/execute! store
{:stream "user-42"
:init nil
:evolve (fn [state event] ...)
:decide (fn [state] ...)}) ; returns events; [] is a valid no-opDesign phase. There is no code yet. The design is settled and tracked as
tickets in the local knot tracker (.tickets/), starting from a
walking skeleton that appends and reads events on both databases.
- CONTEXT.md defines the vocabulary: command, event, stream, consistent projection, outbox, listener.
- docs/adr/ records why projections are transactional instead of async subscriptions, why EDN is the default codec, and why MIT.
A fuller README will come with the documentation ticket, once there is a library to document.