I've become a bit of a CouchDB zealot of late for this exact reason... Native support for incrementally updating map-reduce combined with change-feeds makes implementing event sourcing straightforward. Oh, and it works with PouchDB or Couchbase Lite on web and mobile platforms! A sibling poster wrote Gun(DB?) which would be the next DB I'd try if CouchDB couldn't fit the bill.
If you wanted to reimplement event sourcing in couch, it can be implemented as a versioned merge in a map-reduce view that takes a sequential ordered events (e.g. `ui-event:0000025`) and maps those changes into a "versioned" JSON. This versioned JSON changes leaf values into versioned objects like `"fieldValue": { "_val": 34.00, "_ver": 25 }` which I call property fields. This is necessary because CouchDB is a B+Tree implementation and reduce operations are sequential but not contiguous. The reduce phase merges all events sequentially by choosing property fields with the latest event – making it a CRDT type – and resulting in a single JSON document with the latest fields with "_ver" info for each. This scheme has a drawback that each event needs to have a unique serially ordered ID to work. Not sure how time stamps would work. I chose the ID based scheme to allow the UI be able to know when a user interaction conflicts (a vector clock between) and let it display the conflict to the user or decide how to merge the knew state.
It's not the most efficient but for most moderate sized UI's with a single state tree, it performs fine. Enough to run on a raspberry pi. :)
The only thing I haven't implemented in this is user permissions, but I suspsect using something like JWT tokens could provide a way to "verify" a user event on the CouchDB server.
I'd be curious to know if this scheme would perform much better with an log merge database, but there doesn't seem to be any obvious benefits to me, imho. Alternatively, does anyone else know of other DB's with incremental map-reduce? Postgres materialized views (pre v10) and Mongo map reduce views both seem to require explicit calls to update them after new events.
[edit: mobile phone grammar fixes]
If you wanted to reimplement event sourcing in couch, it can be implemented as a versioned merge in a map-reduce view that takes a sequential ordered events (e.g. `ui-event:0000025`) and maps those changes into a "versioned" JSON. This versioned JSON changes leaf values into versioned objects like `"fieldValue": { "_val": 34.00, "_ver": 25 }` which I call property fields. This is necessary because CouchDB is a B+Tree implementation and reduce operations are sequential but not contiguous. The reduce phase merges all events sequentially by choosing property fields with the latest event – making it a CRDT type – and resulting in a single JSON document with the latest fields with "_ver" info for each. This scheme has a drawback that each event needs to have a unique serially ordered ID to work. Not sure how time stamps would work. I chose the ID based scheme to allow the UI be able to know when a user interaction conflicts (a vector clock between) and let it display the conflict to the user or decide how to merge the knew state.
It's not the most efficient but for most moderate sized UI's with a single state tree, it performs fine. Enough to run on a raspberry pi. :)
The only thing I haven't implemented in this is user permissions, but I suspsect using something like JWT tokens could provide a way to "verify" a user event on the CouchDB server.
I'd be curious to know if this scheme would perform much better with an log merge database, but there doesn't seem to be any obvious benefits to me, imho. Alternatively, does anyone else know of other DB's with incremental map-reduce? Postgres materialized views (pre v10) and Mongo map reduce views both seem to require explicit calls to update them after new events. [edit: mobile phone grammar fixes]