-
Notifications
You must be signed in to change notification settings - Fork 382
fix(server): truncate torn segment tails instead of resurrecting them #3946
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
hubcio
wants to merge
8
commits into
master
Choose a base branch
from
fix/torn-segment-truncate
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
a8240ca
fix(server): truncate torn segment tails instead of resurrecting them
hubcio 2a01e2d
fix(server): bound the damage probe and preserve bytes on refusal
hubcio 1cc830a
fix(partitions): advance index write cursor only after fsync
hubcio 18c107b
chore(repo): move segment size mismatch code from 4044 to 4102
hubcio 0929f69
fix(server): make boot damage scan knob-immune and preemptible
hubcio cfd2265
fix(server): make single-replica recovery tombstones hold
hubcio 7a9c4b3
fix(server): recover a segment whose index file is gone
hubcio c727a1c
fix(server): verify gap-opening batch before adopting its offset
hubcio File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
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
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Blocker: this constant is documented as an invariant, and it is not enforced where batches are actually admitted.
The doc says the ceiling caps "the widest batch record any admission path can persist", and
MAX_RECOVERABLE_BATCH_BYTESinsegment_recovery.rsis derived from it and used to reject headers. But the new validator only checksmessage_bus.max_message_size, and the HTTP produce path never goes through the frame decoder:partition_write_replicatedbuilds the request in-process viabuild_request_message(http/wire.rs:199, called fromhttp/submit.rs:383), soframing::read_message'stotal_size <= max_message_sizecheck (message_bus/src/framing.rs:107-122) never runs.framing::write_messagehas no size check either — only the read side caps — so atreplica_count > 1the primary journals the oversize batch locally and the peer's read rejects the frame, with the bytes already on disk.SendMessages::validate→IggyMessagesBatch::validate(messages_batch.rs:219-226) checksMAX_PAYLOAD_SIZEper message, never the sum, andSendMessagesOwned::from_messages(send_messages.rs:157) computesbatch_lengthwith no ceiling.http.max_request_sizehas no validator in either validators file and is#[config_env(leaf)], so it is env-settable.The code already says this outright at
shard/src/lib.rs:963-968: "Derived from the BUS frame cap, notMAX_PAYLOAD_SIZE: the server never enforces the latter (its only enforcement sites are the legacy server and the SDK batch types), so the largest appendable batch is whatever the message bus will frame." The HTTP path is not framed by the bus, so on that path nothing frames it.Reachability is precise and operator-gated, not accidental: JSON bodies carry base64, so raw payload is ~3/4 of the body, and you need
http.max_request_sizeabove roughly 342 MiB with five or more messages of ≤64 MB each. Shipped default is 2 MB, so there are three orders of magnitude of headroom. But once past it,peek_headerreturnsNoneon a legally admitted, checksum-valid batch: the walk breaks and the tail is silently truncated, orInteriorDamagerefuses and atreplica_count = 1tombstones permanently.Suggested fix: validate
http.max_request_size <= MAX_MESSAGE_SIZE_UPPER_BYTESat boot. Sound because a produce request carries at most one batch and base64 leaves ~25% slack, so bounding the body bounds the record;http/forward.rs:290-297re-reads the same key so forwards inherit it. Optionally add a batch-total check beside the per-message one inIggyMessagesBatch::validate— if so, please reuseIggyError::TooBigMessagePayloadrather than minting a discriminant, since codes are mirrored in the Go and Node tables and a new one for a config-only failure is not worth the regeneration. Note that validator lives in publishediggy_commonand the Rust SDK calls it client-side, so it is a behaviour change in a published crate, and thatMAX_PAYLOAD_SIZE = 64 * 1000 * 1000is decimal while everything here is binary MiB.Either enforce it or drop the "widest batch record any admission path can persist" claim from this doc and from
segment_recovery.rs:78-86. Shipping the claim without the enforcement is the part that will mislead the next reader.Two more things this ceiling needs documented. A deployment currently running above 256 MiB has no non-destructive upgrade path: it cannot boot until the knob is lowered, and once booted recovery treats the wide batches already on disk as implausible and truncates or refuses the segment holding them. Nothing tells the operator to drain and re-produce below the ceiling first. And the validator ordering hides the ceiling error —
validators.rs:164-177runs beforemessage_bus.validate()at:205, somax_message_size = "512 MiB"hits the artifact-floor error first and sends the operator to raisetransfer_artifact_bytes_max; only after doing that do they meet the real ceiling, i.e. two boot cycles to learn the edit is impossible.