You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fluss.apache.org by ja...@apache.org on 2026/02/10 17:35:49 UTC
(fluss) 02/06: [kv] Add zero-offset bucket keys verification in undo recovery test (#2623)
This is an automated email from the ASF dual-hosted git repository.
jark pushed a commit to branch release-0.9
in repository https://gitbox.apache.org/repos/asf/fluss.git
commit 6bfc45d96072ee3ede1845a8a3e3ee4368a75c8a
Author: Yang Wang <oc...@alibaba-inc.com>
AuthorDate: Tue Feb 10 20:13:00 2026 +0800
[kv] Add zero-offset bucket keys verification in undo recovery test (#2623)
---
.../writer/undo/UndoRecoveryManagerITCase.java | 51 ++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/fluss-flink/fluss-flink-common/src/test/java/org/apache/fluss/flink/sink/writer/undo/UndoRecoveryManagerITCase.java b/fluss-flink/fluss-flink-common/src/test/java/org/apache/fluss/flink/sink/writer/undo/UndoRecoveryManagerITCase.java
index 9e7762c30..3ea6ec289 100644
--- a/fluss-flink/fluss-flink-common/src/test/java/org/apache/fluss/flink/sink/writer/undo/UndoRecoveryManagerITCase.java
+++ b/fluss-flink/fluss-flink-common/src/test/java/org/apache/fluss/flink/sink/writer/undo/UndoRecoveryManagerITCase.java
@@ -464,6 +464,57 @@ public class UndoRecoveryManagerITCase {
}));
}
}
+
+ // Verify zero-offset bucket keys after undo recovery.
+ //
+ // Since checkpoint offset is 0, ALL writes to this bucket are undone.
+ // The undo writer uses partial update (targetColumns = {id, price}) with
+ // OVERWRITE mode, so undo only clears target columns — non-target columns
+ // written by other writers or earlier full writes are unaffected.
+ //
+ // - id < 80: These keys were first written by fullWriter in Phase 1, which
+ // populated ALL columns (including non-target columns like name, stock).
+ // Undo clears the target column (price) to null, but the row still exists
+ // because non-target columns retain their values.
+ //
+ // - id >= 100: These keys were ONLY written by partialWriter in Phase 2,
+ // which only populated target columns (id, price). Undo clears those
+ // target columns, leaving no column with data, so the row is effectively
+ // deleted.
+ for (int id : zeroOffsetBucketKeysAfterCheckpoint) {
+ final int keyId = id;
+ verifyFutures.add(
+ lookuper.lookup(row(keyId))
+ .thenAccept(
+ r -> {
+ if (keyId < 80) {
+ // Key has non-target column data from
+ // fullWriter (Phase 1), so the row survives
+ // undo — only target column (price) is cleared.
+ InternalRow result = r.getSingletonRow();
+ assertThat(result)
+ .as(
+ "Zero-offset bucket key %d should still exist (non-target columns retain data)",
+ keyId)
+ .isNotNull();
+ assertThat(result.isNullAt(2))
+ .as(
+ "Zero-offset bucket key %d price (target column) should be null after undo",
+ keyId)
+ .isTrue();
+ } else {
+ // Key was only written via partialWriter
+ // (target columns only) — undo clears all
+ // its data, so the row no longer exists.
+ assertThat(r.getSingletonRow())
+ .as(
+ "Zero-offset bucket key %d should not exist (no non-target column data)",
+ keyId)
+ .isNull();
+ }
+ }));
+ }
+
CompletableFuture.allOf(verifyFutures.toArray(new CompletableFuture[0])).get();
}
}