This is an automated email from the ASF dual-hosted git repository.

amoghj pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg.git


The following commit(s) were added to refs/heads/main by this push:
     new c6b252e97e Core: Skip unnecessary metadata refresh when producing 
snapshot event after merge append (#14709)
c6b252e97e is described below

commit c6b252e97eace78cf31df1d72ff91e7e641049da
Author: gaborkaszab <[email protected]>
AuthorDate: Mon Feb 2 17:50:31 2026 +0100

    Core: Skip unnecessary metadata refresh when producing snapshot event after 
merge append (#14709)
---
 .../apache/iceberg/MergingSnapshotProducer.java    |  7 +++-
 .../org/apache/iceberg/rest/RequestMatcher.java    | 16 +++++++++
 .../org/apache/iceberg/rest/TestRESTCatalog.java   | 39 ++++++++++++++++++++--
 3 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/core/src/main/java/org/apache/iceberg/MergingSnapshotProducer.java 
b/core/src/main/java/org/apache/iceberg/MergingSnapshotProducer.java
index 51d17fbdd0..761f94a830 100644
--- a/core/src/main/java/org/apache/iceberg/MergingSnapshotProducer.java
+++ b/core/src/main/java/org/apache/iceberg/MergingSnapshotProducer.java
@@ -968,7 +968,12 @@ abstract class MergingSnapshotProducer<ThisT> extends 
SnapshotProducer<ThisT> {
   @Override
   public Object updateEvent() {
     long snapshotId = snapshotId();
-    Snapshot justSaved = ops().refresh().snapshot(snapshotId);
+
+    Snapshot justSaved = ops().current().snapshot(snapshotId);
+    if (justSaved == null) {
+      justSaved = ops().refresh().snapshot(snapshotId);
+    }
+
     long sequenceNumber = TableMetadata.INVALID_SEQUENCE_NUMBER;
     Map<String, String> summary;
     if (justSaved == null) {
diff --git a/core/src/test/java/org/apache/iceberg/rest/RequestMatcher.java 
b/core/src/test/java/org/apache/iceberg/rest/RequestMatcher.java
index 18b66e7737..fb93b7c9da 100644
--- a/core/src/test/java/org/apache/iceberg/rest/RequestMatcher.java
+++ b/core/src/test/java/org/apache/iceberg/rest/RequestMatcher.java
@@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.argThat;
 
 import java.util.Map;
 import java.util.Objects;
+import java.util.function.Predicate;
 
 class RequestMatcher {
   private RequestMatcher() {}
@@ -71,6 +72,21 @@ class RequestMatcher {
                 && Objects.equals(req.body(), body));
   }
 
+  static HTTPRequest matches(
+      HTTPRequest.HTTPMethod method,
+      String path,
+      Map<String, String> headers,
+      Map<String, String> parameters,
+      Predicate<Object> pred) {
+    return argThat(
+        req ->
+            req.method() == method
+                && req.path().equals(path)
+                && req.headers().equals(HTTPHeaders.of(headers))
+                && req.queryParameters().equals(parameters)
+                && pred.test(req.body()));
+  }
+
   public static HTTPRequest containsHeaders(
       HTTPRequest.HTTPMethod method, String path, Map<String, String> headers) 
{
     return argThat(
diff --git a/core/src/test/java/org/apache/iceberg/rest/TestRESTCatalog.java 
b/core/src/test/java/org/apache/iceberg/rest/TestRESTCatalog.java
index ad5921c231..d03c5f9b88 100644
--- a/core/src/test/java/org/apache/iceberg/rest/TestRESTCatalog.java
+++ b/core/src/test/java/org/apache/iceberg/rest/TestRESTCatalog.java
@@ -86,6 +86,7 @@ import org.apache.iceberg.exceptions.ServiceFailureException;
 import org.apache.iceberg.expressions.Expressions;
 import org.apache.iceberg.inmemory.InMemoryCatalog;
 import org.apache.iceberg.io.FileIO;
+import org.apache.iceberg.metrics.CommitReport;
 import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
 import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
 import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
@@ -99,6 +100,7 @@ import org.apache.iceberg.rest.auth.AuthSessionUtil;
 import org.apache.iceberg.rest.auth.OAuth2Properties;
 import org.apache.iceberg.rest.auth.OAuth2Util;
 import org.apache.iceberg.rest.requests.CreateTableRequest;
+import org.apache.iceberg.rest.requests.ReportMetricsRequest;
 import org.apache.iceberg.rest.requests.UpdateTableRequest;
 import org.apache.iceberg.rest.responses.ConfigResponse;
 import org.apache.iceberg.rest.responses.CreateNamespaceResponse;
@@ -3519,8 +3521,7 @@ public class TestRESTCatalog extends 
CatalogTests<RESTCatalog> {
                     "parent",
                     RESTUtil.namespaceToQueryParam(parentNamespace, 
expectedSeparator),
                     "pageToken",
-                    ""),
-                null),
+                    "")),
             eq(ListNamespacesResponse.class),
             any(),
             any());
@@ -3648,6 +3649,40 @@ public class TestRESTCatalog extends 
CatalogTests<RESTCatalog> {
         .hasMessageContaining("No in-memory file found for location: " + 
metadataFileLocation);
   }
 
+  @Test
+  public void testNumLoadTableCallsForMergeAppend() {
+    RESTCatalogAdapter adapter = Mockito.spy(new 
RESTCatalogAdapter(backendCatalog));
+    RESTCatalog catalog = catalog(adapter);
+
+    catalog.createNamespace(TABLE.namespace());
+    BaseTable table = (BaseTable) catalog.createTable(TABLE, SCHEMA);
+    table.newAppend().appendFile(FILE_A).commit();
+
+    // loadTable is executed once
+    Mockito.verify(adapter)
+        .execute(matches(HTTPMethod.GET, RESOURCE_PATHS.table(TABLE)), any(), 
any(), any());
+
+    // CommitReport reflects the table state after the commit
+    Mockito.verify(adapter)
+        .execute(
+            matches(
+                HTTPMethod.POST,
+                RESOURCE_PATHS.metrics(TABLE),
+                Map.of(),
+                Map.of(),
+                requestObj ->
+                    requestObj instanceof ReportMetricsRequest reportRequest
+                        && reportRequest.report() instanceof CommitReport 
commitReport
+                        && commitReport.tableName().equals(table.name())
+                        && commitReport.snapshotId() == 
table.currentSnapshot().snapshotId()
+                        && commitReport.sequenceNumber() == 
table.currentSnapshot().sequenceNumber()
+                        && commitReport.operation().equals("append")
+                        && 
commitReport.commitMetrics().addedDataFiles().value() == 1),
+            any(),
+            any(),
+            any());
+  }
+
   private RESTCatalog catalog(RESTCatalogAdapter adapter) {
     RESTCatalog catalog =
         new RESTCatalog(SessionCatalog.SessionContext.createEmpty(), (config) 
-> adapter);

Reply via email to