[flink] Fix batch log scan with empty buckets - #4007
Conversation
Use scanner progress to finish bounded log splits when filtering materializes no records. Add a batch regression test for statistics-filtered log tables. Fixes apache#3872
|
Hi @loserwang1024 and @wuchong, when you have time, could you please help review this PR? |
| if (stoppingOffsetOpt.isPresent()) { | ||
| Long stoppingOffset = stoppingOffsetOpt.get(); | ||
| if (startingOffset >= stoppingOffset) { | ||
| if (startingOffset >= stoppingOffset || stoppingOffset == 0) { |
There was a problem hiding this comment.
In which situation, stoppingOffset == 0?
There was a problem hiding this comment.
This covers a newly created table or partition with no data, where the latest offset is 0. Since EARLIEST_OFFSET is the sentinel value -2, startingOffset >= stoppingOffset evaluates to false even though there are no records to read. Therefore, we need to handle stoppingOffset == 0 explicitly.
| tableScanBuckets.add(scanBucket); | ||
| List<ScanRecord> bucketScanRecords = scanRecords.records(scanBucket); | ||
| Long consumedUpToOffset = scanRecords.consumedUpToOffset(scanBucket); | ||
| if (consumedUpToOffset != null && consumedUpToOffset >= stoppingOffset) { |
There was a problem hiding this comment.
Maybe we can unsubscribe each finished scanBucket directly in forLogRecords here, avoiding duplicate remove logic in two places(removeFinishedSplits).
There was a problem hiding this comment.
Thanks for the suggestion. I kept the unsubscribe logic in fetch() because forLogRecords() is currently responsible for converting ScanRecords into FlinkRecordsWithSplitIds. Moving it there would introduce scanner-state side effects and mix result construction with lifecycle cleanup. There is no duplicate removal implementation here; removeFinishedSplits() remains the single cleanup helper.
|
Thanks @loserwang1024 for taking the time to review this PR. This PR incorporates the fix from PR #3873 for issue #3872, using |
Purpose
Linked issue: close #3972
When a Flink batch job scans a multi-bucket Fluss Log Table with low parallelism, an empty bucket can remain active after its bounded split has finished. Subsequent fetch results may then contain a split ID that Flink has already unregistered.
This change ensures that bounded log splits are completed based on scanner progress and that finished buckets are retired before the next fetch.
Brief change log
consumedUpToOffsetreaches the stopping offset.EARLIEST_OFFSET.Tests
FlinkSourceSplitReaderTestFlink120TableSourceBatchITCase./mvnw -pl fluss-flink/fluss-flink-common -DskipTests verifyAPI and Format
No API or storage format changes.
Documentation
No documentation changes.
Generative AI Disclosure