Conversation
|
This is kind of WIP, in that there is still W to do. But I thought it prudent to get eyes on early. Still todo:-
|
There was a problem hiding this comment.
You could short-circuit the case where one clock dominates the other, returning only the dominant one. Right?
There was a problem hiding this comment.
That requires more analytical thinking than I'm capable of right now (thinking embedded maps more than the container.) Maybe…?
There was a problem hiding this comment.
Oh, right. I'll ponder it a while too, maybe we can figure it out tomorrow.
There was a problem hiding this comment.
Well, tomorrow came and went and we didn't come to any conclusion. That said, I can't see why it isn't safe to ignore one map entirely if its clock is dominated (or even just descended). My intuition says that these no-op merges would be mostly at the get_fsm where replicas are already in-sync, and so there would still be value there, by way of reduced latency.
There was a problem hiding this comment.
@russelldb On second thought, could deferred removes happen without incrementing the clock? If so, then my suggestion is moot.
There was a problem hiding this comment.
Going to let eqc tell me. Deferreds are applied in merge, which merges the clocks.
There was a problem hiding this comment.
OK, deferring this TODO for another branch. Want to get this semantic into the next Beta, optimisation comes after.
|
Can you rebase or merge develop into this so it will merge cleanly (and make borshop happy)? |
|
After the review I can. |
src/riak_dt_emcntr.erl
Outdated
There was a problem hiding this comment.
Nitpick: This doesn't handle the subtly-evil user who increments or decrements by a negative amount.
|
Is it ok that the |
|
@seancribbs good question, I need to look at that some more. I mean, that's a high percentage, I think I need further metrics to see what size the map is, 'cos I suspect that there is still an issue with the state for this test. Luckily I have some expert eyes tomorrow. |
The problem with an embedded pn-counter is when the field is removed and added again. PN-Counter merge takes the max of P and N as the merged value. In the case that a field was removed and re-added P and N maybe be _lower_ than their removed values, and when merged with a replica that has not seen the remove, the remove is lost. This counter adds some causality by storing a `dot` with P and N. Merge takes the max event for each actor, so newer values win over old ones. The rest of the mechanics are the same.
As well as ensuring correct shrinking and fixing generators replace sets with lists for ease of reading when a counter example is found
|
@russelldb I've rebased your branch, cleaning up a duplicate commit and grouping similar work. To get your local copy working:
Ping me if you have trouble with this. |
Disallow negative arguments to embedded counter Document the map semantics
|
OK. Addressed review comments and pushed. Just going to remove |
|
Removed "add" from PB and HTTP APIs basho/riak_pb#93, basho/riak_kv#951 |
|
👍 ffce004 |
Reset-remove semantic on Map Reviewed-by: seancribbs
|
@borshop merge |
With a shared causal context for the map and the CRDTs it embeds, removing a field, and then re-adding it has the effect of removing all the additions to that field when merging with a concurrent update to the field. For example:
The set contains only 'Y' and 'Z', since the remove of the field at A containing 'X' constitutes a remove of 'X'.
However, if the field was not re-added by A the semantic was different, and the result would contain 'X, Y, Z'. This seemed counter-intuitive and confusing. These changes add a temporary tombstone to present fields, so that the removal of a field effects a removal of all dots seen by the field at removal time. But you don't have to re-add the field to see this effect. Neat.
One intuitive way to think of it as like an offline sync of a file system like Dropbox. With this semantic, removing a directory on one machine, and adding a file to that directory on another, merges to the directory being present, with only the added file in it.
There is some oddness with counters, though.
I added a new counter type,
riak_dt_emcntr(see it's docs for more details) that stores adotas latest event against each actors increments and decrements. This is so a field removal can reset the counter value. However, we don't store a dot per increment (that would be crazy inefficient). Counters work will in this scenarioCounter is at 5 (A's dot for the increment is dropped)
However there is an anomaly
The counter is at 15.
Now, technically, A's first increment should be dropped (should it??) and only the second stand, but that does not happen, as we don't keep a dot per increment. This, too, can be spun in the filesystem sense. If you updated a file and concurrently removed it, you wouldn't expect only the diff to survive, but the whole file.
Personally I'm happy enough with the semantic, to enable reset-remove on counters requires a dot per increment (a counter as set of increments) and that is not worth the overhead.
Happy to rebase once the full round of reviewing is done.
OOOOOOOH, And I removed
addfrom the Map API. Problem?