[server] Normalize legacy remote log manifest ranges - #4274
Merged
platinumhamburg merged 3 commits intoSep 11, 2026
Conversation
Normalize overlapping logical ranges when loading remote manifests and before merging new segments. Preserve readable coverage independently of manifest entry order while retaining raw persisted file references for orphan cleanup. Cover legacy loading, containment, ordering, TTL, persistence, and remote reads through KV recovery and FetchLog v0. Fixes apache#4272 Co-Authored-By: Codex <noreply@openai.com> AI-Model: gpt-6 AI-Contributed/Feature: 65/65 AI-Contributed/UT: 367/367
Check logical bounds in a linear pass before copying or sorting segments. Reuse manifests whose logical ranges are already ordered and disjoint, including clipped physical overlaps and gaps. Preserve normalization for unordered or overlapping input. Cover empty, single-segment, contiguous, gapped, and clipped views, plus unordered disjoint ranges. Co-Authored-By: Codex <noreply@openai.com> AI-Model: gpt-6 AI-Contributed/Feature: 23/23 AI-Contributed/UT: 31/31
| .containsExactlyElementsOf(expectedChecksums.subList(20, 30)); | ||
| } | ||
|
|
||
| private List<Long> fetchChecksumsUsingFetchV0(TableBucket bucket, long offset, long endOffset) |
Contributor
There was a problem hiding this comment.
@gyang94 Thanks for the fix! The normalization addresses the legacy overlap issue, and the explicit checks for version 1 and the absence of logical offset fields make the legacy-format coverage clear and deterministic.
One small suggestion: would you consider exercising the actual FetchLog RPC path instead of the custom read loop in fetchChecksumsUsingFetchV0()? Checking the returned segment and position at the shorter segment’s end offset could provide more direct regression coverage.
Replace the simulated FetchLog v0 read loop with an RPC through TabletService. Remove local copies and check the returned segment and byte position at the shorter segment's end, then verify records using the response's file path. Co-Authored-By: Codex <noreply@openai.com> AI-Model: gpt-6 AI-Contributed/Feature: 0/0 AI-Contributed/UT: 178/178
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.
Purpose
Fixes #4272.
Loading a legacy manifest containing
[10,30)followed by[10,20)can make offset 20 unreadable: the shorter segment replaces the longer one in the offset index. Nested ranges with different starts can similarly hide existing records, and subsequent merges can shrink readable coverage.This change establishes a consistent logical view before indexing or merging legacy manifests, independently of entry order.
Brief change log
trimAndMerge()so removing a visible segment cannot restore a hidden range.As with the existing merge logic, normalization assumes overlapping committed records agree; it does not reconcile divergent WAL histories.
Tests
Passed targeted verification on Java 11:
mvn -o -pl fluss-common,fluss-server -am verify \ '-Dtest=RemoteLog*Test,DefaultRemoteLogStorageTest,TieredLocalSegmentTTLTest,CommitRemoteLogManifestITCase' \ -Dsurefire.failIfNoSpecifiedTests=false74c9c6f65: 162 relevant cases (20 in common and 142 in server).verifywith-Dtest=RemoteLogManifestOverlapTest,RemoteLogManifestJsonSerdeTest,RemoteLogTabletOverlapTest,RemoteLogFetcherTest: 58 cases (22 in common and 36 in server), including empty, single-segment, contiguous, gapped, clipped, and unordered views.TabletServiceat the shorter segment's end offset, after local copies have been removed. It checks the returned segment ID and byte position, then reads records using the response's path and position and verifies offsets and checksums in both manifest orders.API and Format
Uses the existing version-1 manifest fields and logical-range model. No RPC or storage-format changes.
Documentation
No new configuration or user-facing feature; no documentation changes.
Generative AI used: Codex (GPT-6).