From 589528c3acb829ec19bae36ae7db204293279506 Mon Sep 17 00:00:00 2001 From: Lari Hotari Date: Wed, 19 Feb 2025 15:30:25 +0200 Subject: [PATCH 1/2] [improve][ci] Upgrade Gradle Develocity Maven Extension to 1.23.1 --- .mvn/extensions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml index 8ceede33b9cdc..22eaa6a1779f4 100644 --- a/.mvn/extensions.xml +++ b/.mvn/extensions.xml @@ -24,7 +24,7 @@ com.gradle develocity-maven-extension - 1.22.2 + 1.23.1 com.gradle From 51563a130eff60d69a2b355ce16710707e2cf546 Mon Sep 17 00:00:00 2001 From: Lari Hotari Date: Fri, 21 Feb 2025 11:24:48 +0200 Subject: [PATCH 2/2] Workaround the deadlock by preventing eager Testcontainers initialization when toString is called --- .../metadata/BaseMetadataStoreTest.java | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/pulsar-metadata/src/test/java/org/apache/pulsar/metadata/BaseMetadataStoreTest.java b/pulsar-metadata/src/test/java/org/apache/pulsar/metadata/BaseMetadataStoreTest.java index 03a6b91b62d4b..4bdb379d8235d 100644 --- a/pulsar-metadata/src/test/java/org/apache/pulsar/metadata/BaseMetadataStoreTest.java +++ b/pulsar-metadata/src/test/java/org/apache/pulsar/metadata/BaseMetadataStoreTest.java @@ -26,6 +26,7 @@ import java.io.File; import java.net.URI; import java.util.Arrays; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletionException; @@ -136,12 +137,12 @@ private Object[][] allImplementations() { // The new connection string won't be available to the test method unless a // Supplier lambda is used for providing the value. return new Object[][]{ - {"ZooKeeper", stringSupplier(() -> zksConnectionString)}, - {"Memory", stringSupplier(() -> memoryConnectionString)}, - {"RocksDB", stringSupplier(() -> rocksdbConnectionString)}, - {"Etcd", stringSupplier(() -> "etcd:" + getEtcdClusterConnectString())}, - {"Oxia", stringSupplier(() -> "oxia://" + getOxiaServerConnectString())}, - {"MockZooKeeper", stringSupplier(() -> mockZkUrl)}, + {"ZooKeeper", providerUrlSupplier(() -> zksConnectionString)}, + {"Memory", providerUrlSupplier(() -> memoryConnectionString)}, + {"RocksDB", providerUrlSupplier(() -> rocksdbConnectionString)}, + {"Etcd", providerUrlSupplier(() -> "etcd:" + getEtcdClusterConnectString(), "etcd:...")}, + {"Oxia", providerUrlSupplier(() -> "oxia://" + getOxiaServerConnectString(), "oxia://...")}, + {"MockZooKeeper", providerUrlSupplier(() -> mockZkUrl)}, }; } @@ -185,16 +186,29 @@ private synchronized String getEtcdClusterConnectString() { return etcdCluster.clientEndpoints().stream().map(URI::toString).collect(Collectors.joining(",")); } - public static Supplier stringSupplier(Supplier supplier) { - return new StringSupplier(supplier); + private static Supplier providerUrlSupplier(Supplier supplier) { + return new ProviderUrlSupplier(supplier); + } + + // Use this method to provide a custom toString value for the Supplier. Use this when Testcontainers is used + // so that a toString call doesn't eagerly trigger container initialization which could cause a deadlock + // with Gradle Develocity Maven Extension. + private static Supplier providerUrlSupplier(Supplier supplier, String toStringValue) { + return new ProviderUrlSupplier(supplier, Optional.ofNullable(toStringValue)); } // Implements toString() so that the test name is more descriptive - private static class StringSupplier implements Supplier { + private static class ProviderUrlSupplier implements Supplier { private final Supplier supplier; + private final Optional toStringValue; + + ProviderUrlSupplier(Supplier supplier) { + this(supplier, Optional.empty()); + } - public StringSupplier(Supplier supplier) { + ProviderUrlSupplier(Supplier supplier, Optional toStringValue) { this.supplier = supplier; + this.toStringValue = toStringValue; } @Override @@ -204,7 +218,9 @@ public String get() { @Override public String toString() { - return get(); + // toStringValue is used to prevent deadlocks which could occur if toString method call eagerly triggers + // Testcontainers initialization. This is the case when Gradle Develocity Maven Extension is used. + return toStringValue.orElseGet(this::get); } }