4444import org .apache .paimon .operation .commit .CommitCleaner ;
4545import org .apache .paimon .operation .commit .CommitKindProvider ;
4646import org .apache .paimon .operation .commit .CommitResult ;
47+ import org .apache .paimon .operation .commit .CommitRollback ;
4748import org .apache .paimon .operation .commit .CommitScanner ;
4849import org .apache .paimon .operation .commit .ConflictDetection ;
4950import org .apache .paimon .operation .commit .ManifestEntryChanges ;
@@ -139,6 +140,7 @@ public class FileStoreCommitImpl implements FileStoreCommit {
139140 private final ManifestFile manifestFile ;
140141 private final ManifestList manifestList ;
141142 private final IndexManifestFile indexManifestFile ;
143+ @ Nullable private final CommitRollback rollback ;
142144 private final CommitScanner scanner ;
143145 private final int numBucket ;
144146 private final MemorySize manifestTargetSize ;
@@ -196,7 +198,8 @@ public FileStoreCommitImpl(
196198 boolean rowTrackingEnabled ,
197199 boolean discardDuplicateFiles ,
198200 ConflictDetection conflictDetection ,
199- @ Nullable StrictModeChecker strictModeChecker ) {
201+ @ Nullable StrictModeChecker strictModeChecker ,
202+ @ Nullable CommitRollback rollback ) {
200203 this .snapshotCommit = snapshotCommit ;
201204 this .fileIO = fileIO ;
202205 this .schemaManager = schemaManager ;
@@ -210,6 +213,7 @@ public FileStoreCommitImpl(
210213 this .manifestFile = manifestFileFactory .create ();
211214 this .manifestList = manifestListFactory .create ();
212215 this .indexManifestFile = indexManifestFileFactory .create ();
216+ this .rollback = rollback ;
213217 this .scanner = new CommitScanner (scan , indexManifestFile , options );
214218 this .numBucket = numBucket ;
215219 this .manifestTargetSize = manifestTargetSize ;
@@ -314,10 +318,13 @@ public int commit(ManifestCommittable committable, boolean checkAppendFiles) {
314318 if (appendCommitCheckConflict ) {
315319 checkAppendFiles = true ;
316320 }
321+
322+ boolean allowRollback = false ;
317323 if (containsFileDeletionOrDeletionVectors (
318324 appendSimpleEntries , changes .appendIndexFiles )) {
319325 commitKind = CommitKind .OVERWRITE ;
320326 checkAppendFiles = true ;
327+ allowRollback = true ;
321328 }
322329
323330 attempts +=
@@ -330,6 +337,7 @@ public int commit(ManifestCommittable committable, boolean checkAppendFiles) {
330337 committable .watermark (),
331338 committable .properties (),
332339 CommitKindProvider .provider (commitKind ),
340+ allowRollback ,
333341 checkAppendFiles ,
334342 null );
335343 generatedSnapshot += 1 ;
@@ -348,6 +356,7 @@ public int commit(ManifestCommittable committable, boolean checkAppendFiles) {
348356 committable .watermark (),
349357 committable .properties (),
350358 CommitKindProvider .provider (CommitKind .COMPACT ),
359+ false ,
351360 true ,
352361 null );
353362 generatedSnapshot += 1 ;
@@ -513,6 +522,7 @@ public int overwritePartition(
513522 committable .watermark (),
514523 committable .properties (),
515524 CommitKindProvider .provider (CommitKind .COMPACT ),
525+ false ,
516526 true ,
517527 null );
518528 generatedSnapshot += 1 ;
@@ -653,6 +663,7 @@ public void commitStatistics(Statistics stats, long commitIdentifier) {
653663 Collections .emptyMap (),
654664 CommitKindProvider .provider (CommitKind .ANALYZE ),
655665 false ,
666+ false ,
656667 statsFileName );
657668 }
658669
@@ -679,6 +690,7 @@ private int tryCommit(
679690 @ Nullable Long watermark ,
680691 Map <String , String > properties ,
681692 CommitKindProvider commitKindProvider ,
693+ boolean allowRollback ,
682694 boolean detectConflicts ,
683695 @ Nullable String statsFileName ) {
684696 int retryCount = 0 ;
@@ -698,6 +710,7 @@ private int tryCommit(
698710 watermark ,
699711 properties ,
700712 commitKind ,
713+ allowRollback ,
701714 latestSnapshot ,
702715 detectConflicts ,
703716 statsFileName );
@@ -750,6 +763,7 @@ private int tryOverwritePartition(
750763 watermark ,
751764 properties ,
752765 commitKindProvider ,
766+ false ,
753767 true ,
754768 null );
755769 }
@@ -764,6 +778,7 @@ CommitResult tryCommitOnce(
764778 @ Nullable Long watermark ,
765779 Map <String , String > properties ,
766780 CommitKind commitKind ,
781+ boolean allowRollback ,
767782 @ Nullable Snapshot latestSnapshot ,
768783 boolean detectConflicts ,
769784 @ Nullable String newStatsFileName ) {
@@ -821,7 +836,9 @@ CommitResult tryCommitOnce(
821836 // latestSnapshotId is different from the snapshot id we've checked for conflicts,
822837 // so we have to check again
823838 List <BinaryRow > changedPartitions = changedPartitions (deltaFiles , indexFiles );
824- if (retryResult != null && retryResult .latestSnapshot != null ) {
839+ if (retryResult != null
840+ && retryResult .latestSnapshot != null
841+ && retryResult .baseDataFiles != null ) {
825842 baseDataFiles = new ArrayList <>(retryResult .baseDataFiles );
826843 List <SimpleFileEntry > incremental =
827844 scanner .readIncrementalChanges (
@@ -845,12 +862,21 @@ CommitResult tryCommitOnce(
845862 .filter (entry -> !baseIdentifiers .contains (entry .identifier ()))
846863 .collect (Collectors .toList ());
847864 }
848- conflictDetection .checkNoConflictsOrFail (
849- latestSnapshot ,
850- baseDataFiles ,
851- SimpleFileEntry .from (deltaFiles ),
852- indexFiles ,
853- commitKind );
865+ Optional <RuntimeException > exception =
866+ conflictDetection .checkConflicts (
867+ latestSnapshot ,
868+ baseDataFiles ,
869+ SimpleFileEntry .from (deltaFiles ),
870+ indexFiles ,
871+ commitKind );
872+ if (exception .isPresent ()) {
873+ if (allowRollback && rollback != null ) {
874+ if (rollback .tryToRollback (latestSnapshot )) {
875+ return RetryCommitResult .ofEmpty (exception .get ());
876+ }
877+ }
878+ throw exception .get ();
879+ }
854880 }
855881
856882 Snapshot newSnapshot ;
@@ -979,7 +1005,7 @@ CommitResult tryCommitOnce(
9791005 } catch (Exception e ) {
9801006 // commit exception, not sure about the situation and should not clean up the files
9811007 LOG .warn ("Retry commit for exception." , e );
982- return new RetryCommitResult (latestSnapshot , baseDataFiles , e );
1008+ return RetryCommitResult . ofContext (latestSnapshot , baseDataFiles , e );
9831009 }
9841010
9851011 if (!success ) {
@@ -996,7 +1022,7 @@ CommitResult tryCommitOnce(
9961022 commitTime );
9971023 commitCleaner .cleanUpNoReuseTmpManifests (
9981024 baseManifestList , mergeBeforeManifests , mergeAfterManifests );
999- return new RetryCommitResult (latestSnapshot , baseDataFiles , null );
1025+ return RetryCommitResult . ofContext (latestSnapshot , baseDataFiles , null );
10001026 }
10011027
10021028 LOG .info (
0 commit comments