[client][server][paimon] Complete historical partition writes - #4120
Conversation
7de8d5e to
dd7af7f
Compare
7f8c03f to
312b033
Compare
230460c to
5657415
Compare
|
Thanks for all the review feedback. After addressing the comments, I believe the following follow-up work is still needed before historical partition writes are production-ready. Remaining production-readiness work
|
13923d7 to
844468f
Compare
|
@wuchong Thanks for you review. Comments have been addressed. |
6e1666e to
839c54d
Compare
839c54d to
b334900
Compare
| * <p>It is null for a normal write and contains the logical partition namespace for a | ||
| * historical write. | ||
| */ | ||
| private volatile @Nullable String originalPartitionName; |
There was a problem hiding this comment.
Should we use a volatile boolean isHistoricalPartition? The original partition name is determinist when the batch is created which is in the physicalTablepath.
| @Nullable Throwable historicalTargetCause = null; | ||
| try { | ||
| if (metadataUpdater.checkAndUpdatePartitionMetadata(historicalPath)) { | ||
| accumulator.rerouteQueuedWritesToHistorical( |
There was a problem hiding this comment.
Add an info log to record which partitions have transitioned to historical partitions.
7af0a2c to
0a71c84
Compare
wuchong
left a comment
There was a problem hiding this comment.
LGTM. I appended a commit to refactor WriteBatch a bit.
|
@wuchong Thanks for the commit. LGTM! I rebase main branch to resolve conflict. |
Route writes for expired partitions through internal historical targets while preserving original partition metadata across PUT_KV and PRODUCE_LOG. Tier historical KV and log records back to their original Paimon partitions, fail writes to confirmed missing targets, and safely clean fully tiered historical KV overlays with leader-epoch and offset guards. Co-Authored-By: Codex <noreply@openai.com> AI-Model: gpt-5 AI-Contributed/Feature: 0/1469 AI-Contributed/UT: 52/2215
Simplify historical write routing, request handling, and Paimon tiering integration while removing redundant tests. Co-Authored-By: Codex <noreply@openai.com> AI-Model: gpt-5 AI-Contributed/Feature: 446/446 AI-Contributed/UT: 576/576
Bind historical write state to the active KV overlay and defer idle cleanup until its deadline after lake progress catches up. Co-Authored-By: Codex <noreply@openai.com> AI-Model: gpt-5 AI-Contributed/Feature: 234/234 AI-Contributed/UT: 129/129
Return a retriable KV storage error while local historical KV state is being initialized or rebuilt. Clarify cleanup-state naming and terminology, and extend the Paimon integration test through post-recovery writes and restarted tiering. Co-Authored-By: Codex <noreply@openai.com> AI-Model: gpt-5 AI-Contributed/Feature: 244/244 AI-Contributed/UT: 239/239
Refresh registered Paimon partition-bucket file sets when the required lake snapshot changes, allowing unchanged local lookup files to remain reusable. Co-Authored-By: Codex <noreply@openai.com> AI-Model: gpt-5 AI-Contributed/Feature: 215/215 AI-Contributed/UT: 125/125
Exclude the plugin-facing LakeTableLookuper interface from the aggregate per-class coverage rule. Co-Authored-By: Codex <noreply@openai.com> AI-Model: gpt-5 AI-Contributed/Feature: 3/3 AI-Contributed/UT: 0/0
Remove the coupled historical KV cleanup mechanism, defer lake lookup refresh I/O until lookup initialization, and simplify historical write version and routing checks. Reroute missing original targets when no request remains in flight, abort only the affected target when handoff is unsafe, and document the remaining retirement ambiguity. Co-Authored-By: Codex <noreply@openai.com> AI-Model: gpt-5.6-sol AI-Contributed/Feature: 1006/1006 AI-Contributed/UT: 543/543
Represent historical write routing with a boolean derived from the original path, log successful partition reroutes, and coalesce lake lookup refresh requests without losing requests that arrive during a refresh. Co-Authored-By: Codex <noreply@openai.com> AI-Model: gpt-5 AI-Contributed/Feature: 121/121 AI-Contributed/UT: 100/100
…ethod AI-Contributed/Feature: 0/19 AI-Contributed/UT: 0/0
7df21cd to
b5213ab
Compare
Generated-by: Codex (GPT-5) following the guidelines
Purpose
Linked issue: close #4119
Complete the end-to-end historical partition write support left as follow-up work by #4001. Writers can write records whose original Paimon partitions have expired through the shared Fluss historical partition while preserving each record's original partition identity. This PR covers client routing, KV and log RPCs, historical KV recovery and lake lookup refresh, and tiering back to the original Paimon partitions.
Why resolve the write target before sending
Historical fallback changes the physical
TableBucketfrom the original partition to the shared historical partition. Writer idempotence is scoped by physicalTableBucket, so these targets have independent writer-ID and batch-sequence namespaces.If the client always sends to the original partition first and waits for the server to report that it no longer exists, the batch has already entered the original target's sequence namespace. Other requests for the same target may also be in flight. Moving queued batches at that point requires pausing the old target, resolving its outstanding responses, preserving order, and assigning new writer IDs and sequences in the historical target. Until that handoff is implemented, an in-flight request makes transparent rerouting unsafe and the client must abort the affected target, which causes a Flink job failover.
To reduce the probability of reaching that case, the client resolves a potentially expired target before enqueueing the record. The client-side retention boundary is only a low-cost hint; refreshed metadata confirms whether the original partition still exists. If it exists, the write remains on the original target. If it is confirmed missing, the batch is created directly in the historical target's idempotence namespace.
This precheck narrows but cannot eliminate the race between metadata resolution and sending. If the server explicitly reports that the original target disappeared during that window, the client reroutes queued batches when no request for that target remains in flight. Otherwise, it aborts only the affected target to preserve idempotence and sequence correctness. The durable retirement and graceful in-flight handoff are tracked by #3820 and #4166; #4161 tracks replacing the client-side retention calculation with periodically refreshed, server-authoritative lifecycle metadata.
Brief change log
PUT_KVandPRODUCE_LOG, version-gate the newPRODUCE_LOGfields, and correlate responses by the actual physical target plus the original partition.PRODUCE_LOGfor primary-key tables so all primary-key writes, including historical writes, go throughPUT_KV.Tests
Validation and targeted suites run during development:
./mvnw -nsu -DskipTests -DskipITs -pl fluss-common,fluss-rpc,fluss-server validate./mvnw -nsu -DskipTests -DskipITs -pl fluss-client,fluss-flink/fluss-flink-common,fluss-lake/fluss-lake-paimon validateServerConnectionTestClientRpcMessageUtilsTest, write-batch tests,RecordAccumulatorTest, andSenderTestHistoricalPartitionTableValidationTest,ServerRpcMessageUtilsTest,HistoricalPartitionTaskExecutorTest, andHistoricalPartitionManagerTestPaimonTieringTest,PaimonLakeTableLookuperTest, andHistoricalPartitionITCaseThe complete
ReplicaManagerTestsuite could not finish locally because host disk usage exceeded the TabletServer test write limit and causedDiskWriteLockedException; CI provides the full validation.API and Format
PRODUCE_LOGfrom version 0 to version 1 and adds optionaloriginal_partition_namefields to bucket requests and responses. Version gates keep version 0 peers compatible.PUT_KVby [server] Support primary-key writes to historical partitions #4001.PaimonWriteResultserialization is used only for shuffle data, not persisted operator state, so no state-compatibility migration is required.Documentation
Updates the historical-partition table option description to cover write access.
Production hardening is tracked separately: