zhuxiangyi commented on code in PR #9667:
URL: https://github.com/apache/paimon/pull/9667#discussion_r3995564323


##########
paimon-spark/paimon-spark-common/src/main/scala/org/apache/paimon/spark/commands/PaimonSparkWriter.scala:
##########
@@ -472,14 +498,32 @@ case class PaimonSparkWriter(
       postCommit(finalMessages)
       return
     }
-    val activeWriteBuilder =
-      Option(directPostponeWriteBuilder).getOrElse(writeBuilder)
-    val tableCommit = activeWriteBuilder.newCommit()
+    val tableCommit: InnerTableCommit =
+      if (directPostponeWriteBuilder != null) {
+        directPostponeWriteBuilder.newCommit()

Review Comment:
   Confirmed and reproduced first: with `bucket = -2`, 
`postpone.default-bucket-num = 1` and complete mode, replaying batch 0 took the 
table from snapshot 1 to snapshot 2, exactly as you saw. Both halves of your 
analysis held up on inspection.
   
   Fixed in 587ad9c14 along the first line you suggested:
   
   - `PostponeFixedBucketWriteBuilder` gained `withCommitUser`, mirroring the 
one on `BatchWriteBuilderImpl`, and the direct builder is created with the 
stable user.
   - The direct path looks the replay up itself, with `latestSnapshotOfUser` 
unbounded, and commits under the batch id only when nothing at or above it has 
been committed. The strict mode bound is left alone: it is what conflict 
detection needs, and I traced its use in `filterCommitted` to #7239/#7275, a 
lookup optimisation whose premise is a commit user that never outlives its base 
snapshot. That premise is exactly what a stable user breaks, so the lookup for 
this path has to be independent of it rather than the bound relaxed for 
everyone.
   
   The test for this configuration also commits a later batch after the replay 
and checks it lands, so that a higher batch id cannot be mistaken for a replay 
— the failure mode in that direction is silent data loss, which is worse than 
the duplicate.
   
   Two things worth recording. First, while looking for a way to observe 
maintenance on this path I found that 
`PrimaryKeyFileStoreTable.newExpireRunnable()` returns null for postpone bucket 
tables, so snapshot expiration is never part of a commit there; a probe that 
expects the direct path to expire snapshots will not see it, regardless of 
`inlineMaintenance`. I restructured the sink so `inlineMaintenance(true)` is 
set once above both streaming branches, where the existing expiration test on 
an append table guards it, and added a core test in `SimpleTableTestBase` that 
commits through `filterAndCommit` with a committer closed after each batch and 
asserts the previous snapshot is expired before the close. Second, the staged 
committer is still outside the replay handling and keeps its warning; I did not 
extend the change there.
   
   The suite is at 11 cases and was run on the 3.2, 3.4, 3.5, 4.0 and 4.1 
modules again.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to