TL;DR — Knew I should’ve checked, now I’ve got a 500 and floaters in my eye
Part of a series
Previous article: Just eyeball it
Next article: Sure no rush
The whole spiel about entities and formlessness was not for nothing, for event sourcing to be useful in any way we need to reduce the chances of bad data ever getting in. As you may or may not know, relational databases do this via a schema. We’re gonna do it the same way.
To recap, an entity is an event stream and every event in the stream is linked together by the unique value which identifies the entity; it’s identity.
To store the schema, we need an atom. All modules should add their schemas to this shared atom before attempting to load any entities. It’s shared global state because it promotes reuse, it’s not fun having to deal with a gajillion million and one representations of an entity.
(def schema-registry
"Used to ensure that the reduced state of the entity is valid.
An entity can only be loaded if a schema is defined for it"
(atom {}))
In a module adding the schema would look like:
(swap! entity/schema-registry conj
{:order (ds/spec {:name ::order
:spec {:uuid uuid?
:amount number?}})}) :city ::imi-pd-spec/city}}})})
Now that that’s out of the way, we can work on a more useful form of aggregate which caters for the kind of cases that would crop up in application code. We have four main use cases: