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

merlimat pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/pulsar.git


The following commit(s) were added to refs/heads/branch-4.0 by this push:
     new 26662e345601 [fix][metadata] Fix orphaned UR parent nodes not cleaned 
up with Oxia metadata backend (#26158)
26662e345601 is described below

commit 26662e3456016bf3cb7328a74bc9bb0b9f5eaebe
Author: Eugene Polozhenkov <[email protected]>
AuthorDate: Tue Jul 7 15:50:12 2026 -0400

    [fix][metadata] Fix orphaned UR parent nodes not cleaned up with Oxia 
metadata backend (#26158)
    
    Co-authored-by: ievgenpolozhenkov <[email protected]>
    (cherry picked from commit 8d5cac607646ccda183373ad7b31e6ffb7e13836)
    Assisted-by: Claude Code (Opus 4.8)
---
 .../pulsar/metadata/api/MetadataStoreException.java    |  8 ++++++++
 .../PulsarLedgerUnderreplicationManager.java           | 18 ++++++++++++------
 .../pulsar/metadata/impl/oxia/OxiaMetadataStore.java   |  2 +-
 .../bookkeeper/LedgerUnderreplicationManagerTest.java  |  4 ++--
 4 files changed, 23 insertions(+), 9 deletions(-)

diff --git 
a/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/api/MetadataStoreException.java
 
b/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/api/MetadataStoreException.java
index 2e2b13a26665..5ddf9a253d8e 100644
--- 
a/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/api/MetadataStoreException.java
+++ 
b/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/api/MetadataStoreException.java
@@ -156,6 +156,14 @@ public class MetadataStoreException extends IOException {
         }
     }
 
+    public static class NotEmptyException extends MetadataStoreException {
+        private static final long serialVersionUID = 1L;
+
+        public NotEmptyException(String path) {
+            super("Key '" + path + "' has children");
+        }
+    }
+
     public static MetadataStoreException unwrap(Throwable t) {
         if (t instanceof MetadataStoreException) {
             return (MetadataStoreException) t;
diff --git 
a/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerUnderreplicationManager.java
 
b/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerUnderreplicationManager.java
index 18871be28c11..1ed465c5c7da 100644
--- 
a/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerUnderreplicationManager.java
+++ 
b/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerUnderreplicationManager.java
@@ -70,6 +70,7 @@ import org.apache.pulsar.metadata.api.NotificationType;
 import org.apache.pulsar.metadata.api.extended.CreateOption;
 import org.apache.pulsar.metadata.api.extended.MetadataStoreExtended;
 import org.apache.pulsar.metadata.impl.ZKMetadataStore;
+import org.apache.pulsar.metadata.impl.oxia.OxiaMetadataStore;
 import org.apache.zookeeper.KeeperException;
 
 @Slf4j
@@ -436,7 +437,8 @@ public class PulsarLedgerUnderreplicationManager implements 
LedgerUnderreplicati
             if (l != null) {
                 store.delete(getUrLedgerPath(ledgerId), 
Optional.of(l.getLedgerNodeVersion()))
                         .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
-                if (store instanceof ZKMetadataStore) {
+                if (store instanceof ZKMetadataStore
+                        || store instanceof OxiaMetadataStore) {
                     try {
                         // clean up the hierarchy
                         String[] parts = getUrLedgerPath(ledgerId).split("/");
@@ -454,11 +456,15 @@ public class PulsarLedgerUnderreplicationManager 
implements LedgerUnderreplicati
                         // It's safe to ignore, it simply means another
                         // ledger in the same hierarchy has been marked as
                         // underreplicated.
-                        if (ee.getCause() instanceof MetadataStoreException && 
ee.getCause().getCause()
-                                instanceof KeeperException.NotEmptyException) {
-                            //do nothing.
-                        } else {
-                            log.warn("Error deleting underrepcalited ledger 
parent node", ee);
+                        // Oxia raises NotEmptyException directly; ZK wraps
+                        // KeeperException.NotEmptyException inside a 
MetadataStoreException.
+                        boolean isNotEmpty =
+                                ee.getCause() instanceof 
MetadataStoreException.NotEmptyException
+                                || (ee.getCause() instanceof 
MetadataStoreException
+                                        && ee.getCause().getCause()
+                                                instanceof 
KeeperException.NotEmptyException);
+                        if (!isNotEmpty) {
+                            log.warn("Error deleting underreplicated ledger 
parent node", ee);
                         }
                     }
                 }
diff --git 
a/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/impl/oxia/OxiaMetadataStore.java
 
b/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/impl/oxia/OxiaMetadataStore.java
index 407a927bda4d..c1e65d4eac1e 100644
--- 
a/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/impl/oxia/OxiaMetadataStore.java
+++ 
b/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/impl/oxia/OxiaMetadataStore.java
@@ -178,7 +178,7 @@ public class OxiaMetadataStore extends 
AbstractMetadataStore {
                         children -> {
                             if (!children.isEmpty()) {
                                 return CompletableFuture.failedFuture(
-                                        new MetadataStoreException("Key '" + 
path + "' has children"));
+                                        new 
MetadataStoreException.NotEmptyException(path));
                             } else {
                                 Set<DeleteOption> delOption =
                                         expectedVersion
diff --git 
a/pulsar-metadata/src/test/java/org/apache/pulsar/metadata/bookkeeper/LedgerUnderreplicationManagerTest.java
 
b/pulsar-metadata/src/test/java/org/apache/pulsar/metadata/bookkeeper/LedgerUnderreplicationManagerTest.java
index ac73491a81c6..6508e6943eec 100644
--- 
a/pulsar-metadata/src/test/java/org/apache/pulsar/metadata/bookkeeper/LedgerUnderreplicationManagerTest.java
+++ 
b/pulsar-metadata/src/test/java/org/apache/pulsar/metadata/bookkeeper/LedgerUnderreplicationManagerTest.java
@@ -300,8 +300,8 @@ public class LedgerUnderreplicationManagerTest extends 
BaseMetadataStoreTest {
         assertEquals(l, lB.get(), "Should be the ledger I marked");
     }
 
-    @Test(dataProvider = "zkImpls", timeOut = 10000)
-    public void testZkMetasStoreMarkReplicatedDeleteEmptyParentNodes(String 
provider, Supplier<String> urlSupplier)
+    @Test(dataProvider = "distributedImpl", timeOut = 10000)
+    public void testMarkReplicatedDeletesEmptyParentNodes(String provider, 
Supplier<String> urlSupplier)
             throws Exception {
         methodSetup(urlSupplier);
 

Reply via email to