A simple filebased eventsourced store
Eventstore is a data store primarily for use with node.js. The store is based on eventsourcing principles (more information below).
Eventstore is awailable as a npm package.
npm install @scriptabuild/eventstore
Travis runs the test suite (mocha) in the latest version of node.js, as well as in v7.6.0.
Have a look at
defineStore
In the classical main-stream architecture the applications we design and build are often stateful. This means that we usually store a snapshot of the objects we deal with in our application in a data store. The snapshot represents the state of the object after the last modification. We continuously overwrite the previous state or snapshot with the newest version in the data store, since there at any one time can be only one version. In doing so, we lose the historical content of the older versions.
For many kinds of data or content this might be more than sufficient since we are not really interested in what was before and how we got to the state we currently are in.
Instead of storing and updating the store to always show a view of the data at some point in time, eventsourcing lets you keep all the changes made to to the data.
The intentions for an event are stored.
This audit trail of operations (while to some degree similar to an RDBMS’ transactionlog) allows restoring the data to any point in time (as long as the log files are kept.)
One important differenting feature of the eventlog vs. the transactionlog (of an RDBMS) is in the way the log intentionally is made accessable to us, as opposed to with a database transaction log who’s only concerns are to ensure integrity of the database, and the ability to rollback a transaction.
Intentions for an event are stored with the event, for a transactionlog entry the real intention is lost.
Replay is a important key feature to the entire eventsourcing system.
As replay is used everytime you need to inflate a model to query, you’ll get more used to dealing with events and playing back the log. Replay has to be a very easy feature to use.
Some of the new habits of working with the eventsource will be:
Martin Fowlers article on Eventsourcing examines more aspects of eventsourcing, and is worth the read.
//TODO: Surely there must be something, mustn’t it?
A read/write model allows you to work with existing data in an eventlog in a persisent way. Any changes made through the model are stored to the eventlog as an ordered and transactional item.
A read model allows you to work with a model created by replaying the event logs. Any changes made to a read only model will be lost when the model is “closed”.
You can also have the concept of a write only model. In this case, you don’t actually need to build a model, so the simplest way to implement this is by just using the log(eventName, eventData)
and logBlock(action)
methods.
Eventstore offers repeatable read isolation level with the transaction/batch model. These transactions can be either commited or rolled back, and Eventstore will handle concurrent writes by retrying the write a preset number of times (before otherwise failing the transaction/batch).
You can design multiple different models to use when working with your event log. These models can be thought of as similar to views or even queries in a SQL database. Eventstore is designed to work with multiple models over the same store. These different models will allow you to view your data in different ways, or even work with them.
Check out the super handy “Patterns for creating a model from the eventlog”
You can also replay all events in the event log to aggregate data without creating a model upfront.
One advantage of creating a model is the ability to create a snapshot. A snapshot is a precomputed state of the model at a given time (ie. at a specific log no.) With this snapshot, you can easily skip the replaying of parts of (or even the whole of) the log, thus making restoring a model consume fewer resources.
If you create multiple models, you will get seperate snapshots for each model. (Snapshots can’t shared between models.)
The LogSchemaTool
is an analyzer tool for your event logs.
It looks at a set of logs to determine what events it holds. It will show number of occurrences, the parameter names and types, as well as the first and last appearances of that event.
The LogSchemaTool
was created to help create new models, but the information gathered and reported could also be helpful to determine when certain functionality was implemented, indicating periods of time when certain events would or wouldn’t have been recorded, thus showing what data potentially is missing.
The LogSchemaTool
is implemented as a read only domain model.
//TODO: show code to use the LogSchemaTool...
Eventstore requires you to include its NPM package in your code, and runs in process. There is no need to set up or run a server process.
Most document databases or relational databases products will typically require the installation of a server process.
Going directly to the filesystem is perhaps the simplest to set up, but you have no abstractions to handle concurrency nor transactions and more.
//TODO: Create comprehensive table of more test results from different types of workloads.