TL;DR — Does anyone know what happened?
Part of a series
Previous article: Sure no rush
I’ve had an Apple Watch for 5 to 6 years now. I wouldn’t say that it’s a necessity and I can definitely go without it but when the one I have is on its last legs I will most probably get another one. I vaguely remember the initial launch, it was met with a ton of scepticism considering there were watches like the Pebble at the time which were already pretty successful. In just 5 years since it’s launch in 2015, sales for the watch were about double that of the entire Swiss watch market which includes the likes of Rolex, Omega and Patek Philippe.
I really only use it for notifications and light fitness tracking. I don’t close any rings or track my sleep or my heart rate or need the emergency SOS features. But if the features I used were the only things it could do, I would probably not have gotten one. Yeah the watch is good and it works very well — vertical integration and all — but I think what I really value is ... I’m not sure what the word is, convenience? It’s not that much more inconvenient to use my phone for notifications or fitness tracking. Maybe versatility? I could be a fitness junkie, couch potato or elderly and I wouldn’t have to go out and get something else, I can stick to the same device. Yeah, that’s the one.
I think what makes the Apple Watch such a big hit is also what makes a tool good. Tools that can be used in many scenarios without too much hassle. An Apple Watch is very complex to be versatile; it needs to maintain a Bluetooth connection with your phone, poll heart rate, check the weather, check for updates, remind you to stand, remind you to wash hands and so on. With tools we use to build applications, it’s the opposite. It’s gotta be simple so that we can wire things up as we see fit and make more complicated things out of it. Simple also because it means less moving parts for less headaches and a longer youth.
Just felt chatty. So far we’ve seen a few of the benefits offered by event sourcing for different stakeholders: speed (business), flexibility (developers and design), traceability (prod support) and auditability (legal).
One other aspect of event sourcing which is incredibly useful is the ability to replay events up to a certain point in time. Need to investigate something that was working before? Rewind to the time when things were fine and find the difference.
We already have most of what we need to do this, we just need be able to load events up till a certain point in time (difference between load-by-entity-id is in bold):
(require '[honey.sql :as sql]
'[next.jdbc :as jdbc])
(defn load-by-entity-id-and-revision
"Load all events for an entity by its id and revision.
Events are ordered by the time occurred and their revision.
If snapshots are available starts from the snapshot."
[connectable entity-id revision]
(let [query (-> {:with [[[:snapshots {:columns [:entity-id :revision :event-agent
:time-occurred :time-observed :event-data]}]
{:select [:entity-id :revision :event-agent
:time-occurred :time-observed :event-data]
:from :event-journal
:where [:and
[:= :entity-id entity-id]
[:= :event-agent (:snapshot agents/system-agents)]
**[:<= :revision revision]**]
:order-by [[:time-occurred :asc] [:revision :asc]]}]
[[:events {:columns [:entity-id :revision :event-agent
:time-occurred :time-observed :event-data]}]
{:select [:entity-id :revision :event-agent
:time-occurred :time-observed :event-data]
:from :event-journal
:where [:and
[:= :entity-id entity-id]
[:> :revision [:coalesce
{:select [[[:max :revision]]]
:from :snapshots}
0]]
**[:<= :revision revision]**]
:order-by [[:time-occurred :asc] [:revision :asc]]}]]
:union [{:select [:*]
:from :snapshots}
{:select [:*]
:from :events
:order-by [[:time-occurred :asc] [:revision :asc]]}]}
(sql/format))
result (jdbc/execute! connectable query)]
result))
Now all we need to do is feed the events to aggregate and examine the state of the entity at a certain point in time. I didn’t support loading multiple entities at a time because the use case is for testing and debugging which is more targeted.
You will notice that what makes event sourcing so versatile and powerful is due to the fact that we have taken away functionality. With event sourcing we’ve taken away the idea of updates, schemas, joins, BCNF and transactions. All we need is a storage system that allows us to retrieve events efficiently in order. Yes yes, less is more.