Conversation
Since yrs 0.27 a struct whose same-client predecessors are missing, but whose origin, right origin and parent are present, integrates behind a skip: readable, but absent from pending, from the monitor_update payload and from diffs past the hole. update_gaps/2 compares the update's per-client insertion runs with the doc's state vector and returns the first missing clock for each client that would leave such a hole.
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #276.
Since yrs 0.27 (y-crdt/y-crdt#618), a struct whose same-client predecessors are missing, but whose origin, right origin and parent are all present, is integrated behind a
Block::Skipinstead of being held as pending. It is readable afterwards, but it is not inget_pending_update/1,monitor_updatedelivers<<0, 0>>for the transaction, and a diff encoded for a peer whose state vector reaches the hole leaves it out.BlockStore.skipsispub(crate), so callers cannot see the hole. y-crdt/y-crdt#673 asks about that upstream, and y-crdt/y-crdt#670 tracks a related retry bug.Yex.Doc.update_gaps(doc, update_v1) :: {:ok, %{client_id => clock}} | {:error, term()}answers the question before the update is applied. It decodes the update, takesUpdate::insertions(true)(per-client clock runs, Skip blocks excluded, so a hole inside the update shows as two runs), and walks each client's runs from the doc's clock for that client:An empty map means applying the update cannot leave a hole. The doc's state vector comes from the open transaction inside
Doc.transaction/3, followingprune_pending/1.Why "starts above the doc's clock" is exactly the skip condition and not an approximation: in yrs 0.28 a skip is created in one place,
Update::integrate, for a struct with no missing dependency whose clock is above the end of that client's block list.txn.state_vector()reports the start of a client's first skip, which is never above the list end, so every struct that would create a skip starts above the state-vector clock. Within one update, once a struct pends, the rest of that client's structs pend with it, so none can slip in behind.insertions(true)includes deleted and GC'd structs, so a GC range does not look like a hole.It does not cover dependencies on other clients' structs or delete ranges. Those stay on the pending path, and the docs point to
get_pending_update/1,get_pending_ds/1andprune_pending/1for them. A doc that already holds a hole reports the hole's first clock for every update at or past it.Tests
k,x,y;xwithheld):%{1 => 1}on a doc holding onlyk,%{}oncexis applied.yis readable, pending isnil,monitor_updategets<<0, 0>>, and a diff for a peer holdingklacksy.%{}.merge_updatesresult with an internal Skip is reported, on an empty doc and on a doc holdingk.Doc.transaction/3; garbage bytes return{:error, _}.cargo fmt --check,cargo clippy -- -D warnings,mix format --check-formatted,mix credo,mix compile --warnings-as-errorsandmix test(647 tests) pass with the NIF built from source.