Repository navigation
Conversation
Lance creates a branch by committing the clone and then writing the ref put-if-absent, whose conflict reads nothing back. A failed create that read its ref back absent force-deleted the clone and retried under the same native name, though the ref put may still have been in flight; a late ref then named a deleted clone. A failed native create now reads its ref back. Matching contents are a lost acknowledgement. An absent ref after a committed clone and a failure that is not a definite refusal is read again with a re-issue's pauses, then stays in doubt, as an in-doubt manifest publication, and keeps the clone. Only a ref that cannot land has its clone reclaimed; that failure is unpublished, and the catalog retries it once under a fresh native name.
|
Revise. The create path no longer deletes a clone whose branch ref may still land. WhyLance 13 The old WhatA failed native create now reads its ref back.
The catalog does not retry an in-doubt create. HTTP maps that error to 500 GQT cannot inject a lost ref put. The Rust owners are the right tier, and the new Blocking
The schema permit is held only until I checked that sequence on this head. An in-doubt create left With The class is every reclamation of a clone whose ref put may still land. This change stops the reclaim inside the failed create. It leaves the collector, which already exists to delete ref-less trees. Put the rule in one owner: native-tree retention. A versioned ref-less Keeping every such tree forever leaks clones whose ref was never sent (the process died after the clone commit, or the refusal path died before reclaim). That leak is the cost of one retention rule. Age does not prove the put cannot land. A per-tree witness written only on the in-doubt path would let the collector tell the two cases apart. A second writer of the ref, with bytes Lance did not mint, is a larger mechanism. This PR is right not to add that writer. Optional
Tradeoffs and liabilityThe poll is the right local substitute for a re-issue. Lance does not return the The change removes a same-name retry that deleted the clone. It adds an in-doubt outcome, the poll, and a kept clone. The kept clone is not durable against the next
#1176 re-issues conditional control-object writes and edits this same RFC section and the storage-failures page. The split is consistent: re-issue when OmniGraph owns the put, read back when Lance owns it. Expect a doc conflict. #1181 edits cleanup tests. It does not change this retention rule. ValidationHead At the merge base, a temporary Failed in 0.01 s. Panic: At the head:
On this head, a temporary test then called CI on LimitationsNo full Inline comments
|
Why
Lance 13 creates a branch in two phases. It commits the clone, then writes the ref put-if-absent (
put_ref_if_absent). The ref write's conflict reads nothing back, and its error says nothing about the object.create_branch_recoverablyread the ref back after a failure. When it found the ref absent, it force-deleted the clone and retried under the same native name. The ref put might still have been in flight and could land after that delete, leaving a live ref that names a deleted clone. Unretired native refs define logical branches, so that is a broken branch.The storage-outcomes RFC (§2, "Refs and tags") says an ambiguous create whose ref is absent on read-back stays in doubt, and that branch creation mints a fresh native name per attempt. Issue #1067 is the origin.
What
A failed native create reads its ref back and decides from what it can prove:
outcome_unknownon the server) and keeps the clone, so a late ref names a whole branch.Unpublished.create_branch_recoverablynow makes one attempt.Catalog::create_branch_frommints the native name, and it retries once under a fresh one only after anUnpublishedfailure.Tests
branch_control::tests::native_create_reads_its_ref_back_before_deciding_issue_1067faults the ref put each way:No path sends a second ref put.
omnigraph-catalog:branch_create_retries_a_refused_ref_under_a_fresh_native_name_issue_1067: two ref puts under two names, the first clone reclaimed, one live incarnation.branch_create_whose_ref_may_land_stays_in_doubt_issue_1067: in doubt, no retry, the clone kept; when the held ref lands, the branch lists and opens.Open question
No later write fences a late ref. Each attempt's ref has its own
{logical}.{ULID}name, so a user who repeats an in-doubt create mints a second incarnation. If the first ref then lands,list_graph_branchesrefuses the whole graph until one incarnation is removed. The user page says to list branches before repeating. Closing this needs one of two things:Validation
branch_control::in core (20 tests), the catalogbranch_createandissue_1067tests with the candidate-tag test now on the shared conditional-put session (9), and the storageissue_1067tests (17): all pass.branching::,point_in_time::andmerge_cleanup::integration suites: 76 passed.-D warningson storage, core, catalog and engine. The local toolchain is 1.98 and the repository pins 1.97.1; two 1.98-only lints on untouched code were allowed locally.cargo fmt --check,check-docs.pyandtypos.native_branch_controls_reclassify_lost_acknowledgements, and the workspace suite. CI runs both.DST was not run. Its storage injects faults above the adapter, and branch creation's storage calls change only on a failure path, so the cost golden does not change.