linguoxuan commented on code in PR #576:
URL: https://github.com/apache/iceberg-cpp/pull/576#discussion_r2986921930


##########
src/iceberg/update/update_snapshot_reference.h:
##########
@@ -134,6 +134,8 @@ class ICEBERG_EXPORT UpdateSnapshotReference : public 
PendingUpdate {
 
   Kind kind() const final { return Kind::kUpdateSnapshotReference; }
 
+  bool IsRetryable() const override { return false; }

Review Comment:
   When used within an external transaction, SnapshotManager.commit() does not 
call transaction.commitTransaction():
   ```
   // SnapshotManager.java
   public void commit() {
       commitIfRefUpdatesExist();
       if (!isExternalTransaction) { 
           transaction.commitTransaction();
       }
   } 
   ```
   The retry then happens in the outer 
BaseTransaction.commitSimpleTransaction() → applyUpdates(). During retry, 
applyUpdates() resets this.current = underlyingOps.current() (refreshed 
metadata), then re-calls update.commit(). But UpdateSnapshotReferencesOperation 
holds this.base captured at construction time (the old metadata). When commit() 
calls ops.commit(base, updated), TransactionTableOperations.commit() checks:
   ```
   // BaseTransaction.java
   public void commit(TableMetadata underlyingBase, TableMetadata metadata) {
       if (underlyingBase != current) {
           throw new CommitFailedException("Table metadata refresh is 
required");
       }
       ...
   } 
   ```
   This throws CommitFailedException, caught as PendingUpdateFailedException 
(which is not CommitFailedException), terminating the retry loop immediately.
   
   CommitFailedException is caught by applyUpdates() and wrapped as 
PendingUpdateFailedException (which is not CommitFailedException), terminating 
the retry loop immediately.
   ```
   private void applyUpdates(TableOperations underlyingOps) {
       if (base != underlyingOps.refresh()) {
         // use refreshed the metadata
         this.base = underlyingOps.current();
         this.current = underlyingOps.current();
         for (PendingUpdate update : updates) {
           // re-commit each update in the chain to apply it and update current
           try {
             update.commit();
           } catch (CommitFailedException e) {
             // Cannot pass even with retry due to conflicting metadata 
changes. So, break the
             // retry-loop.
             throw new PendingUpdateFailedException(e);
           }
         }
       }
     }
   ```
   
   So Java's UpdateSnapshotReferencesOperation also cannot be retried within an 
external transaction. Our IsRetryable() = false is consistent with Java's 
behavior.



-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to