feat(dlv): the client speaks the generic endpoints, and restart resolves every fenced parent - #775
Open
cryptskii wants to merge 1 commit into
Open
feat(dlv): the client speaks the generic endpoints, and restart resolves every fenced parent#775cryptskii wants to merge 1 commit into
cryptskii wants to merge 1 commit into
Conversation
…ves every fenced parent
Rev 15 §15.5 / Req 15.8 / Req 16.5: the concrete HTTP BindingTransport that
makes the sans-IO engine (PR 2) and its fence (PR 3) drive real storage members,
plus the restart-recovery driver.
binding_http_transport: HttpBindingTransport over POST /api/v2/storage/binding/
{read,cas}, with a pure codec over the SINGLE canonical proto (dsm::types::proto)
the node itself decodes, so the two sides cannot drift. Every answer carries the
member's member_id and register_incarnation; the transport reports both and the
runner authenticates them against the committed member before counting (Req 15.8).
A read maps returned cells BACK to requested keys and treats a reordered,
duplicated, or incomplete set as unavailable, so a member cannot shift a record
onto the wrong key or forge a partial read (Req 15.13). A 503 or transport
failure is unavailable; INVALID_STORAGE_ENCODING and EXPECTATION_MISMATCH come
back in the 200 body and map through; UNAVAILABLE never counts.
recover_unresolved_fences: the canonical restart entry (Req 16.5). It lists every
non-terminal trader-parent fence and hands each to a resume_one that reconstructs
the transaction from the fence's stored set and immutable bundle address and
drives it with run_fenced. A fence whose bundle is not yet retrievable is left
fenced and surfaced unresolved, so the parent cannot advance until a later pass.
One worker per fence.
The reconstruction (catalog resolve + GetImmutable + settlement-bundle parse to
K(B) and the trader successor) is settlement-specific, so resume_one is supplied
by the settle path in PR 5.
Rust 1.98.0: workspace board 4020/0, make lint 0, production_safety_checks 0.
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.
PR 4 of the QuorumBind restoration. The concrete HTTP
BindingTransport(the SDK adapter, Req 15.8) that makes the PR 2 engine and PR 3 fence drive real storage members, plus the restart-recovery driver (Req 16.5). Builds on #774.The adapter
quorum_bind_runnerdrives the sans-IO engine over aBindingTransport;HttpBindingTransportis its production implementation over the two generic endpoints Class N exposes:POST /api/v2/storage/binding/read—ReadBinding, public.POST /api/v2/storage/binding/cas—CompareExchangeMany, device auth.The wire messages are the single canonical protobuf definitions (
dsm::types::proto) the node itself decodes, so the two sides cannot drift. The node's own endpoint tests prove it honors those messages; this PR proves the client builds and parses the same ones.Attribution (Req 15.8). Every answer carries the member's
member_idandregister_incarnation; the transport reports both, and the runner (PR 2) authenticates them against the committed member before counting. The transport itself adds no trust — it only relays what the member said. The node stays application-blind: the transport sends opaque keys, an expected digest, and a canonical record, never a claim, vault, or route.A read maps cells back to keys.
parse_read_responseindexes the returned cells by key and rebuilds the record list in the requested order, and treats a response that omits or duplicates a requested key as unavailable, not a partial answer. A member that reorders or drops cells cannot shift a record onto the wrong key or forge an incomplete read (Req 15.13). A non-200 (503, or a transport failure) is unavailable;INVALID_STORAGE_ENCODINGandEXPECTATION_MISMATCHcome back in the 200 body and map through faithfully, whileUNAVAILABLEnever counts.The restart driver
recover_unresolved_fencesis the canonical restart entry (Req 16.5): it loads every locally frozen transaction whose trader-parent fence is not terminal (list_unresolved_fences) and hands each to aresume_onethat reconstructs the transaction from the fence's stored storage set and immutable bundle address and drives it withrun_fenced. A fence whose bundle is not yet retrievable is left fenced and surfaced as unresolved, so the parent cannot advance until a later pass resolves it. One worker per fence, in insertion order.The reconstruction itself — resolving the set from the catalog, retrieving the bundle bytes via
GetImmutable, and parsingK(B)and the trader successor out of the settlement bundle — is settlement-specific and belongs to the settle path, soresume_oneis supplied there (PR 5). This PR delivers the driver, the transport it runs over, and the fence bookkeeping it enforces.Tests
binding_http_transport, 4): a CAS request round-trips through the node message and a non-canonical replacement is refused; a read answer maps records back to their keys regardless of response order and carries attribution; a read missing a requested key is unavailable, not a partial answer; CAS outcomes map andUNAVAILABLE/ non-200 do not count.quorum_bind_runner, +1): two unresolved fences on different parents — the one whose bundle is retrievable resolves to a terminal outcome, the other is left fenced and its parent still blocks all successors.Verification (Rust 1.98.0)
make lint— exit 0--workspace --exclude dsm_storage_node --release) — 4020 passed, 0 failed (75 suites)production_safety_checks(all-features clippy + TLA+) — exit 0 (TLA+ included)Not in this PR (by design)
resume_onereconstruction (catalog resolve +GetImmutable+ settlement-bundle parse toK(B)/successor) and wiring the transport into the live settle paths — PR 5.