You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polaris.apache.org by yu...@apache.org on 2026/06/17 01:12:11 UTC
(polaris) branch main updated: Fix: retry logic for table commits in CatalogHandlerUtils (#4748)
This is an automated email from the ASF dual-hosted git repository.
flyrain pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/polaris.git
The following commit(s) were added to refs/heads/main by this push:
new 638247647c Fix: retry logic for table commits in CatalogHandlerUtils (#4748)
638247647c is described below
commit 638247647c27667697675df01d2163043121e656
Author: Ayush Saxena <ay...@apache.org>
AuthorDate: Wed Jun 17 06:42:07 2026 +0530
Fix: retry logic for table commits in CatalogHandlerUtils (#4748)
---
.../catalog/iceberg/CatalogHandlerUtils.java | 1 +
.../iceberg/AbstractLocalIcebergCatalogTest.java | 39 ++++++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/CatalogHandlerUtils.java b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/CatalogHandlerUtils.java
index 1e7a602c3d..8aedda1925 100644
--- a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/CatalogHandlerUtils.java
+++ b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/CatalogHandlerUtils.java
@@ -420,6 +420,7 @@ public class CatalogHandlerUtils {
.run(
taskOps -> {
TableMetadata base = isRetry.get() ? taskOps.refresh() : taskOps.current();
+ isRetry.set(true);
TableMetadata.Builder metadataBuilder = TableMetadata.buildFrom(base);
TableMetadata newBase = base;
diff --git a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractLocalIcebergCatalogTest.java b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractLocalIcebergCatalogTest.java
index a7f36a943e..e0222dd3ec 100644
--- a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractLocalIcebergCatalogTest.java
+++ b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractLocalIcebergCatalogTest.java
@@ -53,6 +53,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -858,6 +859,44 @@ public abstract class AbstractLocalIcebergCatalogTest extends CatalogTests<Local
this.assertFiles(catalog.loadTable(TABLE), FILE_B);
}
+ @Test
+ public void testCommitRetriesWithRefreshOnFailure() {
+ LocalIcebergCatalog catalog = this.catalog();
+ if (this.requiresNamespaceCreate()) {
+ catalog.createNamespace(NS);
+ }
+
+ catalog.buildTable(TABLE, SCHEMA).withPartitionSpec(SPEC).create();
+ catalog.loadTable(TABLE).newFastAppend().appendFile(FILE_A).commit();
+
+ TableOperations realOps = ((BaseTable) catalog.loadTable(TABLE)).operations();
+ List<MetadataUpdate> updates =
+ List.of(new MetadataUpdate.SetProperties(Map.of("test-key", "test-value")));
+ List<UpdateRequirement> requirements =
+ List.of(new UpdateRequirement.AssertTableUUID(realOps.current().uuid()));
+ UpdateTableRequest request = UpdateTableRequest.create(TABLE, requirements, updates);
+
+ TableOperations spyOps = spy(realOps);
+ AtomicBoolean firstCommit = new AtomicBoolean(true);
+ doAnswer(
+ invocation -> {
+ if (firstCommit.compareAndSet(true, false)) {
+ // Perform a real concurrent modification through the catalog
+ catalog.loadTable(TABLE).newFastAppend().appendFile(FILE_B).commit();
+ throw new CommitFailedException("concurrent modification detected");
+ }
+ return invocation.callRealMethod();
+ })
+ .when(spyOps)
+ .commit(any(), any());
+
+ CatalogHandlerUtils catalogHandlerUtils = new CatalogHandlerUtils(5, false);
+ TableMetadata result = catalogHandlerUtils.commit(spyOps, request);
+
+ Mockito.verify(spyOps, Mockito.atLeastOnce()).refresh();
+ Assertions.assertThat(result.properties()).containsEntry("test-key", "test-value");
+ }
+
@Test
public void testValidateNotificationWhenTableAndNamespacesDontExist() {
Assumptions.assumeTrue(