diff --git a/pricenode/src/main/java/bisq/price/PriceProvider.java b/pricenode/src/main/java/bisq/price/PriceProvider.java index 13b1dc7b0a..863d740acf 100644 --- a/pricenode/src/main/java/bisq/price/PriceProvider.java +++ b/pricenode/src/main/java/bisq/price/PriceProvider.java @@ -17,12 +17,15 @@ package bisq.price; +import bisq.common.UserThread; + import org.springframework.context.SmartLifecycle; import java.time.Duration; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import org.slf4j.Logger; @@ -45,17 +48,17 @@ public abstract class PriceProvider implements SmartLifecycle, Supplier { @Override public final T get() { - if (!isRunning()) - throw new IllegalStateException("call start() before calling get()"); - return cachedResult; } @Override public final void start() { - // we call refresh outside the context of a timer once at startup to ensure that - // any exceptions thrown get propagated and cause the application to halt - refresh(); + // do the initial refresh asynchronously + UserThread.runAfter(() -> { + try { refresh(); } catch (Throwable t) { + log.warn("initial refresh failed", t); + } + }, 1, TimeUnit.MILLISECONDS); timer.scheduleAtFixedRate(new TimerTask() { @Override diff --git a/pricenode/src/main/java/bisq/price/mining/FeeRateService.java b/pricenode/src/main/java/bisq/price/mining/FeeRateService.java index 43116dd24a..7234e636c8 100644 --- a/pricenode/src/main/java/bisq/price/mining/FeeRateService.java +++ b/pricenode/src/main/java/bisq/price/mining/FeeRateService.java @@ -27,6 +27,9 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * High-level mining {@link FeeRate} operations. */ @@ -34,6 +37,7 @@ import java.util.concurrent.atomic.AtomicLong; class FeeRateService { private final List providers; + protected final Logger log = LoggerFactory.getLogger(this.getClass()); /** * Construct a {@link FeeRateService} with a list of all {@link FeeRateProvider} @@ -56,6 +60,10 @@ class FeeRateService { // Process each provider, retrieve and store their fee rate providers.forEach(p -> { FeeRate feeRate = p.get(); + if (feeRate == null) { + log.warn("feeRate is null, provider={} ", p.toString()); + return; + } String currency = feeRate.getCurrency(); if ("BTC".equals(currency)) { sumOfAllFeeRates.getAndAdd(feeRate.getPrice()); diff --git a/pricenode/src/main/java/bisq/price/spot/ExchangeRateService.java b/pricenode/src/main/java/bisq/price/spot/ExchangeRateService.java index 6fcf4a6eb2..e1300b6d5a 100644 --- a/pricenode/src/main/java/bisq/price/spot/ExchangeRateService.java +++ b/pricenode/src/main/java/bisq/price/spot/ExchangeRateService.java @@ -61,6 +61,8 @@ class ExchangeRateService { Map aggregateExchangeRates = getAggregateExchangeRates(); providers.forEach(p -> { + if (p.get() == null) + return; Set exchangeRates = p.get(); // Specific metadata fields for specific providers are expected by the client, @@ -136,6 +138,8 @@ class ExchangeRateService { private Map> getCurrencyCodeToExchangeRates() { Map> currencyCodeToExchangeRates = new HashMap<>(); for (ExchangeRateProvider p : providers) { + if (p.get() == null) + continue; for (ExchangeRate exchangeRate : p.get()) { String currencyCode = exchangeRate.getCurrency(); if (currencyCodeToExchangeRates.containsKey(currencyCode)) { diff --git a/pricenode/src/test/java/bisq/price/mining/providers/MempoolFeeRateProviderTest.java b/pricenode/src/test/java/bisq/price/mining/providers/MempoolFeeRateProviderTest.java index e15a3e18a7..f9d3fe43cd 100644 --- a/pricenode/src/test/java/bisq/price/mining/providers/MempoolFeeRateProviderTest.java +++ b/pricenode/src/test/java/bisq/price/mining/providers/MempoolFeeRateProviderTest.java @@ -28,6 +28,7 @@ import java.time.Instant; import org.junit.jupiter.api.Test; +import static java.lang.Thread.sleep; import static org.junit.Assert.assertTrue; /** @@ -66,6 +67,7 @@ public class MempoolFeeRateProviderTest { // Initialize provider dummyProvider.start(); + try { sleep(1000); } catch (InterruptedException e) { } dummyProvider.stop(); return dummyProvider; @@ -86,6 +88,7 @@ public class MempoolFeeRateProviderTest { // Initialize provider dummyProvider.start(); + try { sleep(1000); } catch (InterruptedException e) { } dummyProvider.stop(); return dummyProvider; diff --git a/pricenode/src/test/java/bisq/price/spot/ExchangeRateServiceTest.java b/pricenode/src/test/java/bisq/price/spot/ExchangeRateServiceTest.java index 61d2ffbee6..4b681d68ea 100644 --- a/pricenode/src/test/java/bisq/price/spot/ExchangeRateServiceTest.java +++ b/pricenode/src/test/java/bisq/price/spot/ExchangeRateServiceTest.java @@ -44,6 +44,7 @@ import ch.qos.logback.core.read.ListAppender; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import static java.lang.Thread.sleep; import static java.util.Arrays.asList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; @@ -287,6 +288,7 @@ public class ExchangeRateServiceTest { // Initialize provider dummyProvider.start(); + try { sleep(1000); } catch (InterruptedException e) { } dummyProvider.stop(); return dummyProvider; @@ -322,6 +324,7 @@ public class ExchangeRateServiceTest { // Initialize provider dummyProvider.start(); + try { sleep(1000); } catch (InterruptedException e) { } dummyProvider.stop(); return dummyProvider;