This is an automated email from the ASF dual-hosted git repository.
merlimat pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git
The following commit(s) were added to refs/heads/master by this push:
new 8d5cac607646 [fix][metadata] Fix orphaned UR parent nodes not cleaned
up with Oxia metadata backend (#26158)
8d5cac607646 is described below
commit 8d5cac607646ccda183373ad7b31e6ffb7e13836
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]>
---
.../pulsar/metadata/api/MetadataStoreException.java | 8 ++++++++
.../bookkeeper/PulsarLedgerUnderreplicationManager.java | 16 +++++++++++-----
.../pulsar/metadata/impl/oxia/OxiaMetadataStore.java | 2 +-
.../bookkeeper/LedgerUnderreplicationManagerTest.java | 4 ++--
4 files changed, 22 insertions(+), 8 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 898832a18986..76649f08175b 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
@@ -172,6 +172,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 1c9648af175b..d1b299848881 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
@@ -68,6 +68,7 @@ import org.apache.pulsar.metadata.api.extended.CreateOption;
import org.apache.pulsar.metadata.api.extended.MetadataStoreExtended;
import org.apache.pulsar.metadata.impl.DualMetadataStore;
import org.apache.pulsar.metadata.impl.ZKMetadataStore;
+import org.apache.pulsar.metadata.impl.oxia.OxiaMetadataStore;
import org.apache.zookeeper.KeeperException;
@CustomLog
@@ -434,7 +435,8 @@ public class PulsarLedgerUnderreplicationManager implements
LedgerUnderreplicati
store.delete(getUrLedgerPath(ledgerId),
Optional.of(l.getLedgerNodeVersion()))
.get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
if (store instanceof ZKMetadataStore
- || store instanceof DualMetadataStore) {
+ || store instanceof DualMetadataStore
+ || store instanceof OxiaMetadataStore) {
try {
// clean up the hierarchy
String[] parts = getUrLedgerPath(ledgerId).split("/");
@@ -452,10 +454,14 @@ 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 {
+ // 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().exception(ee).log("Error deleting
underreplicated ledger parent node");
}
}
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 336c1d942ffa..ed1bc9c80a16 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
@@ -187,7 +187,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 =
deleteOptions(opts, expectedVersion);
CompletableFuture<Boolean> result =
client.delete(path, delOption);
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 205d617c4aca..a35e60dec9bc 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
@@ -299,8 +299,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);