Repository navigation
Conversation
There was a problem hiding this comment.
nit: this still says "groups whose catalog commits failed", but groups rejected by the new pre-check never reach the catalog. Maybe "groups whose batch failed to commit or was rejected because a delete for one of its files was committed after planning"
There was a problem hiding this comment.
Updated in 3491bfe: FailedGroups now covers batches that failed to commit or were rejected because a delete for one of their files was committed after planning.
| return result, fmt.Errorf("validate partial rewrite batch %d against its planning snapshot: %w", batchNum, err) | ||
| } | ||
|
|
||
| failedCommits++ |
There was a problem hiding this comment.
Nothing pins this increment. If I replace it with _ = failedCommits, all the TestRewrite|Compaction tests still pass. The only MaxFailedCommits test goes through cat.failOn. Since the doc now says these rejections count toward the bound, could you add a case with MaxFailedCommits: 1 where two batches get rejected, and assert the "maximum failed commits reached" error?
There was a problem hiding this comment.
Added TestRewriteDataFiles_PartialProgressRejectedBatchesCountTowardMaxFailedCommits in 3491bfe: three batches, peer deletes absorbed into batches 2 and 3, MaxFailedCommits: 1. It asserts the "maximum failed commits reached" error wrapping ErrConflictingDeleteFiles. Replacing the increment with _ = failedCommits makes it fail.
nssalian
left a comment
There was a problem hiding this comment.
I ran the new test against the merge-base rewrite_data_files.go and it fails at :868 with both groups completing. On base I can also see the actual symptom: the deleted row comes back (4 rows instead of 3) and the peer's delete is dropped as dead. With the fix it stays at 3 rows and the delete stays live. The same holds for a three-batch run where the peer delete targets the third batch. A peer delete on a file outside the rewrite doesn't trigger a false rejection. This lines up with Java's validateFromSnapshot(startingSnapshotId) in RewriteDataFilesCommitManager, just checked before the batch writes anything. It needs a rebase. On current main the new test's tx.AddFiles is AddDataFilesByPath after #2308, and concurrentTestCatalog conflicts with the new restConflicts field. Two small things I left comments for
803bd00 to
3491bfe
Compare
|
Thanks @nssalian, and for checking it against base and the three-batch case. Rebased onto main: |
Partial-progress compaction plans every group once, then commits batches one by one, each starting from the previous batch's committed table. When a batch's refresh-and-replay retry rebases onto a peer snapshot, that snapshot becomes the next batch's base, so the next batch's commit-time validator never sees it. If the peer added a position delete or deletion vector for a data file in a later batch, that batch rewrote the file from tasks planned without the delete, then CollectDeadPositionDeletes removed the delete as dead, bringing the deleted rows back. Before rewriting a batch, run the rewrite conflict rules over every snapshot committed since planning. A conflicting batch is recorded in FailedGroups and counts toward MaxFailedCommits, like a failed commit, and nothing is written for it.
Address review: count planning-snapshot rejections toward MaxFailedCommits in a test, and update the FailedGroups doc to cover batches rejected before reaching the catalog. Rebase onto main (AddFiles is now AddDataFilesByPath).
3491bfe to
ff11d28
Compare
Problem
Partial-progress
RewriteDataFilescan bring back rows that a concurrent writer deleted.Groups are planned once, then committed batch by batch, and each batch starts from the table the previous batch committed (
recordCommittedRewriteBatch). Withcommit.retry.num-retries> 0:CollectDeadPositionDeletesthen finds P pointing at a rewritten file and removes it as dead.The same applies to a deletion vector for F, which goes through the same validator branch. Equality deletes are not affected, because any concurrent equality delete fails the batch that would absorb it.
Without retries, batch 1 fails on the stale head and so does every later batch, so nothing is lost. A non-partial rewrite validates the whole window and is rejected with
ErrConflictingDeleteFiles.Fix
Before rewriting a batch,
validateNoNewDeletesSincePlanningrunsvalidateNoNewDeletesForRewrittenFilesover every snapshot committed on the branch between the planning metadata and the current table. Together with the existing commit-time validator, which covers current to the catalog head, every snapshot since planning is now checked.A conflicting batch is handled like a failed commit: its groups go to
FailedGroupswithErrConflictingDeleteFiles, it counts towardMaxFailedCommits, and the run continues. The check runs before the batch is executed, so nothing is written for it. TheMaxFailedCommitsdoc now mentions these rejections.Testing
TestRewriteDataFiles_PartialProgressRejectsDeleteAbsorbedByEarlierBatchuses a one-shotbeforeCommithook onconcurrentTestCatalogto land a file-scoped position delete for a batch-2 file just before batch 1 commits. It checks that batch 1 completes, batch 2 fails withErrConflictingDeleteFiles, the deleted row stays deleted, the delete stays live, and the rejected batch leaves no outputs. Without the fix, both groups complete and the deleted row comes back.go test ./table/... ./cmd/iceberg/...passes.