Event Sourcing in Javascript

What is event sourcing (from a Bozo's perspective)?

Event sourcing is essentially the practice of storing a system's data in its most natural form, events. Rather than worrying about my database tables and codifying my data model into a db instead I store all of the events that have happened. So in DB land we're talking one table called Events with some columns with metadata about the event (to be covered later) and a data column. The data column is a blob field that the business objects can interpret to replay the event happening to them.

Why event sourcing?
There are a ton of benefits as well as some costs to choosing this architectural style. For myself, on this project, I chose it to learn more about event sourcing through experience and I don't fancy myself enough of an expert to give guidance here. The reasons I am interested in it are:
  • A data model that integrates logging- I step through exactly what my user did.
  • Optimizations become views of data- Is calculating your users state too slow? Need SQL? No problem. Run through all of the events and store them in OR tables for fast querying. Think of it as a cache. When a new event is added that invalidates the cache, play that event against your SQL tables as well and you're good to go.
  • Migrations maybe easier(?)- Your conceptual or data model change? No problem, blow away those SQL tables and build new ones based off of the events.
  • A data model that can handle multiple changes to the same data at the same time and no information loss. Because we're just collecting events, the UI may not show the data, but it's still in the system and able to be retrieved if need be.
  • Undo supported by default- Make a change but want to take it back? Go back to a previous moment in time demarcated by... EVENTS. :)
My Experiment
I'm building a small inventory system for a school cafeteria and in an effort to remain engaged and finish it I thought I'd add the wrinkle of letting this be my first pure event sourcing system. I've posted the code online here: https://github.com/jcbozonier/HeeHaw

Interesting results so far...
As I said at the start of this post, I'm doing this as a javascript RIA. The server in my example will be nothing more than Yet Another Event Store. That's been a somewhat surprising result. How I'm going to store the data and everything... just an implementation concern. Since right now the whole app can be brought back to its current state using just the event stream I know that all I need to do to provide persistence is to send the events to the server.... or the browser's local storage... or I can store them in gists via Github's API... the list goes on. 

In the meantime I can run a fully functional version of the system without DB/server access as long as I'm content with no cross session state persistence. MongoDB/Heroku might be pretty damn quick to deploy on but DropBox is even faster.

A negative interesting result? It's taken me a long time to do a fairly CRUDy app. Bending my mind around storing these events and driving the system off of them has been painful to say the least. Also most of my events bubble up from my event store directly to my views without any real logic needing to be done. This will change as the app becomes more complex, but still just wanted to point it out.

You might be wondering, what does a javascript event store look like?

Like this: 

And what do the events look like? Here's an example:

That's the event that fires when an inventory item is added to the system. One interesting aspect of this is the "generate_guid()" function call. I'm used to letting the DB handle that detail for me, but it always bugged me that my business objects couldn't handle that. Now that I use GUIDs I can. Just generate a random ID and assign it to an object.... There's a chance of a collision but there are 3.4x10^38 different possibilities. There are articles on the efficacy of GUIDs/UUIDs please Google for them at your leisure.

More coming shortly
As I make more progress on the app I'm building, I'll add another post. In the meantime I wanted to throw something out here to record my thoughts.