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

nastra 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 9f04b05090 Nessie: Check namespace existence at the ref HEAD in 
listNamespaces (#18035)
9f04b05090 is described below

commit 9f04b05090ade75d50eef5f244914181393adbb7
Author: Eunbin Son <[email protected]>
AuthorDate: Fri Nov 6 00:29:49 2026 +0900

    Nessie: Check namespace existence at the ref HEAD in listNamespaces (#18035)
    
    listNamespaces(Namespace) mixed two commit points inside one method. The
    parent namespace existence check called 
api.getContent().reference(getReference()),
    which pins the request to the hash the client cached when it first resolved
    the reference. The child listing right below it used 
withReference(api.getEntries()),
    which sends only the branch name for a mutable reference so the server 
answers
    from the HEAD of the ref. A client that had not seen a newer commit 
therefore
    got NoSuchNamespaceException for a namespace another client had just 
created,
    even though the child listing would have found it.
    
    Use the withReference(api.getContent()) idiom for the existence check so 
both
    halves of the method read the same commit. loadNamespaceMetadata() in the 
same
    class already reads namespace content that way.
    
    The three remaining api.getContent().reference(getReference()) calls in this
    class (createNamespace, dropNamespace, updateProperties) are left alone. 
They
    are pre-checks that run right before a commit against that same hash, so
    pinning the hash there is the intended behavior.
    
    Generated-by: Claude Code
    
    * Nessie: Reword test comment and use containsExactly in TestMultipleClients
    
    Review follow-up for listNestedNamespacesFromAnotherClient. The first
    listNamespaces() call does not pin the other client to a hash; it only
    forces the client to resolve its reference before the commits below so
    the hash it caches is older than those commits. Say that instead of
    "pins", and use containsExactly since the listing has a single entry.
    
    Generated-by: Claude Code
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
    
    ---------
    
    Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
---
 .../org/apache/iceberg/nessie/NessieIcebergClient.java     |  6 +-----
 .../org/apache/iceberg/nessie/TestMultipleClients.java     | 14 ++++++++++++++
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git 
a/nessie/src/main/java/org/apache/iceberg/nessie/NessieIcebergClient.java 
b/nessie/src/main/java/org/apache/iceberg/nessie/NessieIcebergClient.java
index a59db82daa..9616855a71 100644
--- a/nessie/src/main/java/org/apache/iceberg/nessie/NessieIcebergClient.java
+++ b/nessie/src/main/java/org/apache/iceberg/nessie/NessieIcebergClient.java
@@ -272,11 +272,7 @@ public class NessieIcebergClient implements AutoCloseable {
         org.projectnessie.model.Namespace root =
             org.projectnessie.model.Namespace.of(namespace.levels());
         Content existing =
-            api.getContent()
-                .reference(getReference())
-                .key(root.toContentKey())
-                .get()
-                .get(root.toContentKey());
+            
withReference(api.getContent()).key(root.toContentKey()).get().get(root.toContentKey());
         if (existing == null) {
           throw new NoSuchNamespaceException("Namespace does not exist: %s", 
namespace);
         }
diff --git 
a/nessie/src/test/java/org/apache/iceberg/nessie/TestMultipleClients.java 
b/nessie/src/test/java/org/apache/iceberg/nessie/TestMultipleClients.java
index 883dc9d2f0..43dd9fc0ae 100644
--- a/nessie/src/test/java/org/apache/iceberg/nessie/TestMultipleClients.java
+++ b/nessie/src/test/java/org/apache/iceberg/nessie/TestMultipleClients.java
@@ -111,6 +111,20 @@ public class TestMultipleClients extends BaseTestIceberg {
             "Cannot list child namespaces from 'db1': ref '%s' is no longer 
valid", branch);
   }
 
+  @Test
+  void listNestedNamespacesFromAnotherClient() {
+    // make the other client resolve its reference now, so the hash it caches 
is older than the
+    // commits below
+    assertThat(anotherCatalog.listNamespaces()).isEmpty();
+
+    catalog.createNamespace(Namespace.of("db1"), Collections.emptyMap());
+    catalog.createNamespace(Namespace.of("db1", "sub1"), 
Collections.emptyMap());
+
+    // the parent check must read the HEAD of the ref, not the hash the other 
client cached
+    assertThat(anotherCatalog.listNamespaces(Namespace.of("db1")))
+        .containsExactly(Namespace.of("db1", "sub1"));
+  }
+
   @Test
   public void testLoadNamespaceMetadata() throws NessieConflictException, 
NessieNotFoundException {
     assertThatThrownBy(() -> 
catalog.loadNamespaceMetadata(Namespace.of("namespace1")))

Reply via email to