This looks really nice. The lack of automatic merging was really the last hurdle preventing me from wanting to use Riak.
One issue: I'm surprised that the merge algorithm seems to generally pick the last write as the winner. For example about registers, the docs say: "The most chronologically recent value wins, based on timestamps". But that's not always correct: For example, if client A reads version 10 and writes version 11, and then some client B has version 9 and writes version 12, you have a conflict where node A's version should win even though it's older, since it's history is more correct.
Or is the documentation just ambiguously worded? It says the algorithm is _weighted_ towards last-write-wins, but also that it takes history into consideration.
Only last-write-wins registers use last-write-wins to resolve conflicts. Maps and Sets and Flags use an Add-Wins/Observed-Remove semantic based on fine grained causality tracking methods borrowed from dotted version vectors, counters are vectors of actor->count pairs. None of these types use temporal time at all.
For something like a single string register inside a Map (which is the register you refer to) a simple LWW seemed adequate. Maybe in future we can add some more complex type here, maybe with causal history + timestamp arbitration (like Riak's allow_mult=false.)
One issue: I'm surprised that the merge algorithm seems to generally pick the last write as the winner. For example about registers, the docs say: "The most chronologically recent value wins, based on timestamps". But that's not always correct: For example, if client A reads version 10 and writes version 11, and then some client B has version 9 and writes version 12, you have a conflict where node A's version should win even though it's older, since it's history is more correct.
Or is the documentation just ambiguously worded? It says the algorithm is _weighted_ towards last-write-wins, but also that it takes history into consideration.