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);