diff --git a/common/src/main/java/bisq/common/persistence/PersistenceManager.java b/common/src/main/java/bisq/common/persistence/PersistenceManager.java index ba9d62625be..77a777d8203 100644 --- a/common/src/main/java/bisq/common/persistence/PersistenceManager.java +++ b/common/src/main/java/bisq/common/persistence/PersistenceManager.java @@ -410,7 +410,16 @@ private void maybeStartTimerForPersistence() { } } + public void forcePersistNow() { + // Tor Bridges settings are edited before app init completes, require persistNow to be forced, see writeToDisk() + persistNow(null, true); + } + public void persistNow(@Nullable Runnable completeHandler) { + persistNow(completeHandler, false); + } + + private void persistNow(@Nullable Runnable completeHandler, boolean force) { long ts = System.currentTimeMillis(); try { // The serialisation is done on the user thread to avoid threading issue with potential mutations of the @@ -420,7 +429,7 @@ public void persistNow(@Nullable Runnable completeHandler) { // For the write to disk task we use a thread. We do not have any issues anymore if the persistable objects // gets mutated while the thread is running as we have serialized it already and do not operate on the // reference to the persistable object. - getWriteToDiskExecutor().execute(() -> writeToDisk(serialized, completeHandler)); + getWriteToDiskExecutor().execute(() -> writeToDisk(serialized, completeHandler, force)); long duration = System.currentTimeMillis() - ts; if (duration > 100) { @@ -433,10 +442,11 @@ public void persistNow(@Nullable Runnable completeHandler) { } } - public void writeToDisk(protobuf.PersistableEnvelope serialized, @Nullable Runnable completeHandler) { - if (!allServicesInitialized.get()) { + private void writeToDisk(protobuf.PersistableEnvelope serialized, @Nullable Runnable completeHandler, boolean force) { + if (!allServicesInitialized.get() && !force) { log.warn("Application has not completed start up yet so we do not permit writing data to disk."); - UserThread.execute(completeHandler); + if (completeHandler != null) + UserThread.execute(completeHandler); return; } diff --git a/core/src/main/java/bisq/core/user/Preferences.java b/core/src/main/java/bisq/core/user/Preferences.java index 70eef439fb2..7ae65616c35 100644 --- a/core/src/main/java/bisq/core/user/Preferences.java +++ b/core/src/main/java/bisq/core/user/Preferences.java @@ -679,7 +679,7 @@ public void setResyncSpvRequested(boolean resyncSpvRequested) { public void setBridgeAddresses(List bridgeAddresses) { prefPayload.setBridgeAddresses(bridgeAddresses); // We call that before shutdown so we dont want a delay here - requestPersistence(); + persistenceManager.forcePersistNow(); } // Only used from PB but keep it explicit as it may be used from the client and then we want to persist @@ -690,17 +690,17 @@ public void setPeerTagMap(Map peerTagMap) { public void setBridgeOptionOrdinal(int bridgeOptionOrdinal) { prefPayload.setBridgeOptionOrdinal(bridgeOptionOrdinal); - requestPersistence(); + persistenceManager.forcePersistNow(); } public void setTorTransportOrdinal(int torTransportOrdinal) { prefPayload.setTorTransportOrdinal(torTransportOrdinal); - requestPersistence(); + persistenceManager.forcePersistNow(); } public void setCustomBridges(String customBridges) { prefPayload.setCustomBridges(customBridges); - requestPersistence(); + persistenceManager.forcePersistNow(); } public void setBitcoinNodesOptionOrdinal(int bitcoinNodesOptionOrdinal) { diff --git a/p2p/src/main/java/bisq/network/p2p/NetworkNodeProvider.java b/p2p/src/main/java/bisq/network/p2p/NetworkNodeProvider.java index e8cf8d92385..03652b970f5 100644 --- a/p2p/src/main/java/bisq/network/p2p/NetworkNodeProvider.java +++ b/p2p/src/main/java/bisq/network/p2p/NetworkNodeProvider.java @@ -80,7 +80,7 @@ private TorMode getTorMode(BridgeAddressProvider bridgeAddressProvider, boolean useSafeCookieAuthentication) { return controlPort != Config.UNSPECIFIED_PORT ? new RunningTor(torDir, controlPort, password, cookieFile, useSafeCookieAuthentication) : - new NewTor(torDir, torrcFile, torrcOptions, bridgeAddressProvider.getBridgeAddresses()); + new NewTor(torDir, torrcFile, torrcOptions, bridgeAddressProvider); } @Override diff --git a/p2p/src/main/java/bisq/network/p2p/network/NewTor.java b/p2p/src/main/java/bisq/network/p2p/network/NewTor.java index 33f6d9ca69a..7cd6589cc86 100644 --- a/p2p/src/main/java/bisq/network/p2p/network/NewTor.java +++ b/p2p/src/main/java/bisq/network/p2p/network/NewTor.java @@ -51,19 +51,20 @@ public class NewTor extends TorMode { private final File torrcFile; private final String torrcOptions; - private final Collection bridgeEntries; + private final BridgeAddressProvider bridgeAddressProvider; - public NewTor(File torWorkingDirectory, @Nullable File torrcFile, String torrcOptions, Collection bridgeEntries) { + public NewTor(File torWorkingDirectory, @Nullable File torrcFile, String torrcOptions, BridgeAddressProvider bridgeAddressProvider) { super(torWorkingDirectory); this.torrcFile = torrcFile; this.torrcOptions = torrcOptions; - this.bridgeEntries = bridgeEntries; + this.bridgeAddressProvider = bridgeAddressProvider; } @Override public Tor getTor() throws IOException, TorCtlException { long ts1 = new Date().getTime(); + Collection bridgeEntries = bridgeAddressProvider.getBridgeAddresses(); if (bridgeEntries != null) log.info("Using bridges: {}", bridgeEntries.stream().collect(Collectors.joining(","))); diff --git a/p2p/src/test/java/bisq/network/p2p/network/TorNetworkNodeTest.java b/p2p/src/test/java/bisq/network/p2p/network/TorNetworkNodeTest.java index 3b544da4e59..33bc3d79126 100644 --- a/p2p/src/test/java/bisq/network/p2p/network/TorNetworkNodeTest.java +++ b/p2p/src/test/java/bisq/network/p2p/network/TorNetworkNodeTest.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.List; import java.util.concurrent.CountDownLatch; import org.slf4j.Logger; @@ -55,7 +56,7 @@ public void testTorNodeBeforeSecondReady() throws InterruptedException, IOExcept latch = new CountDownLatch(1); int port = 9001; TorNetworkNode node1 = new TorNetworkNode(port, TestUtils.getNetworkProtoResolver(), false, - new NewTor(new File("torNode_" + port), null, "", new ArrayList()), null); + new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null); node1.start(new SetupListener() { @Override public void onTorNodeReady() { @@ -82,7 +83,7 @@ public void onRequestCustomBridges() { latch = new CountDownLatch(1); int port2 = 9002; TorNetworkNode node2 = new TorNetworkNode(port2, TestUtils.getNetworkProtoResolver(), false, - new NewTor(new File("torNode_" + port), null, "", new ArrayList()), null); + new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null); node2.start(new SetupListener() { @Override public void onTorNodeReady() { @@ -140,7 +141,7 @@ public void testTorNodeAfterBothReady() throws InterruptedException, IOException latch = new CountDownLatch(2); int port = 9001; TorNetworkNode node1 = new TorNetworkNode(port, TestUtils.getNetworkProtoResolver(), false, - new NewTor(new File("torNode_" + port), null, "", new ArrayList()), null); + new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null); node1.start(new SetupListener() { @Override public void onTorNodeReady() { @@ -166,7 +167,7 @@ public void onRequestCustomBridges() { int port2 = 9002; TorNetworkNode node2 = new TorNetworkNode(port2, TestUtils.getNetworkProtoResolver(), false, - new NewTor(new File("torNode_" + port), null, "", new ArrayList()), null); + new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null); node2.start(new SetupListener() { @Override public void onTorNodeReady() { @@ -217,4 +218,8 @@ public void onFailure(@NotNull Throwable throwable) { node2.shutDown(latch::countDown); latch.await(); } + + public List getBridgeAddresses() { + return new ArrayList<>(); + } }