handle server error conditions better, and if using public server try another

This commit is contained in:
Craig Raw 2021-04-28 11:23:17 +02:00
parent e4264d0199
commit 6f5ee7c695
5 changed files with 35 additions and 6 deletions

View file

@ -79,6 +79,7 @@ public class AppController implements Initializable {
public static final double TAB_LABEL_GRAPHIC_OPACITY_ACTIVE = 0.95; public static final double TAB_LABEL_GRAPHIC_OPACITY_ACTIVE = 0.95;
public static final String LOADING_TRANSACTIONS_MESSAGE = "Loading wallet, select Transactions tab to view..."; public static final String LOADING_TRANSACTIONS_MESSAGE = "Loading wallet, select Transactions tab to view...";
public static final String CONNECTION_FAILED_PREFIX = "Connection failed: "; public static final String CONNECTION_FAILED_PREFIX = "Connection failed: ";
public static final String TRYING_ANOTHER_SERVER_MESSAGE = "trying another server...";
@FXML @FXML
private MenuItem saveTransaction; private MenuItem saveTransaction;
@ -1539,7 +1540,9 @@ public class AppController implements Initializable {
@Subscribe @Subscribe
public void connectionStart(ConnectionStartEvent event) { public void connectionStart(ConnectionStartEvent event) {
statusUpdated(new StatusEvent(event.getStatus(), 120)); if(!statusBar.getText().contains(TRYING_ANOTHER_SERVER_MESSAGE)) {
statusUpdated(new StatusEvent(event.getStatus(), 120));
}
} }
@Subscribe @Subscribe
@ -1558,12 +1561,15 @@ public class AppController implements Initializable {
@Subscribe @Subscribe
public void disconnection(DisconnectionEvent event) { public void disconnection(DisconnectionEvent event) {
serverToggle.setDisable(false); serverToggle.setDisable(false);
if(!AppServices.isConnecting() && !AppServices.isConnected() && !statusBar.getText().startsWith(CONNECTION_FAILED_PREFIX)) { if(!AppServices.isConnecting() && !AppServices.isConnected() && !statusBar.getText().startsWith(CONNECTION_FAILED_PREFIX) && !statusBar.getText().contains(TRYING_ANOTHER_SERVER_MESSAGE)) {
statusUpdated(new StatusEvent("Disconnected")); statusUpdated(new StatusEvent("Disconnected"));
} }
if(statusTimeline == null || statusTimeline.getStatus() != Animation.Status.RUNNING) { if(statusTimeline == null || statusTimeline.getStatus() != Animation.Status.RUNNING) {
statusBar.setProgress(0); statusBar.setProgress(0);
} }
for(Wallet wallet : getOpenWallets().keySet()) {
tabLabelStopAnimation(wallet);
}
} }
@Subscribe @Subscribe
@ -1620,6 +1626,9 @@ public class AppController implements Initializable {
public void walletHistoryFailed(WalletHistoryFailedEvent event) { public void walletHistoryFailed(WalletHistoryFailedEvent event) {
walletHistoryFinished(new WalletHistoryFinishedEvent(event.getWallet())); walletHistoryFinished(new WalletHistoryFinishedEvent(event.getWallet()));
tabs.getTabs().stream().filter(tab -> tab.getUserData() instanceof WalletTabData && ((WalletTabData) tab.getUserData()).getWallet() == event.getWallet()).forEach(this::tabLabelAddFailure); tabs.getTabs().stream().filter(tab -> tab.getUserData() instanceof WalletTabData && ((WalletTabData) tab.getUserData()).getWallet() == event.getWallet()).forEach(this::tabLabelAddFailure);
if(getOpenWallets().containsKey(event.getWallet())) {
statusUpdated(new StatusEvent("Error retrieving wallet history" + (Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER ? ", " + TRYING_ANOTHER_SERVER_MESSAGE : "")));
}
} }
@Subscribe @Subscribe

View file

@ -250,8 +250,7 @@ public class AppServices {
onlineProperty.addListener(onlineServicesListener); onlineProperty.addListener(onlineServicesListener);
if(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER) { if(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER) {
List<String> otherServers = Arrays.stream(PublicElectrumServer.values()).map(PublicElectrumServer::getUrl).filter(url -> !url.equals(Config.get().getPublicElectrumServer())).collect(Collectors.toList()); Config.get().changePublicServer();
Config.get().setPublicElectrumServer(otherServers.get(new Random().nextInt(otherServers.size())));
connectionService.setPeriod(Duration.seconds(PUBLIC_SERVER_RETRY_PERIOD_SECS)); connectionService.setPeriod(Duration.seconds(PUBLIC_SERVER_RETRY_PERIOD_SECS));
} }
@ -715,4 +714,14 @@ public class AppServices {
connectionService.start(); connectionService.start();
} }
} }
@Subscribe
public void walletHistoryFailed(WalletHistoryFailedEvent event) {
if(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER && connectionService != null && connectionService.isRunning()) {
onlineProperty.set(false);
log.info("Connection to " + Config.get().getServerAddress() + " failed, reconnecting to another server...");
Config.get().changePublicServer();
onlineProperty.set(true);
}
}
} }

View file

@ -11,8 +11,11 @@ import org.slf4j.LoggerFactory;
import java.io.*; import java.io.*;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Currency; import java.util.Currency;
import java.util.List; import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
public class Config { public class Config {
private static final Logger log = LoggerFactory.getLogger(Config.class); private static final Logger log = LoggerFactory.getLogger(Config.class);
@ -333,6 +336,11 @@ public class Config {
flush(); flush();
} }
public void changePublicServer() {
List<String> otherServers = Arrays.stream(PublicElectrumServer.values()).map(PublicElectrumServer::getUrl).filter(url -> !url.equals(getPublicElectrumServer())).collect(Collectors.toList());
setPublicElectrumServer(otherServers.get(new Random().nextInt(otherServers.size())));
}
public String getCoreServer() { public String getCoreServer() {
return coreServer; return coreServer;
} }

View file

@ -19,7 +19,7 @@ import java.util.concurrent.atomic.AtomicLong;
public class SimpleElectrumServerRpc implements ElectrumServerRpc { public class SimpleElectrumServerRpc implements ElectrumServerRpc {
private static final Logger log = LoggerFactory.getLogger(SimpleElectrumServerRpc.class); private static final Logger log = LoggerFactory.getLogger(SimpleElectrumServerRpc.class);
private static final int MAX_TARGET_BLOCKS = 25; private static final int MAX_TARGET_BLOCKS = 25;
private static final int MAX_RETRIES = 10; private static final int MAX_RETRIES = 5;
private static final int RETRY_DELAY = 1; private static final int RETRY_DELAY = 1;
private final AtomicLong idCounter = new AtomicLong(); private final AtomicLong idCounter = new AtomicLong();

View file

@ -24,6 +24,7 @@ public class TcpTransport implements Transport, Closeable {
public static final int DEFAULT_PORT = 50001; public static final int DEFAULT_PORT = 50001;
private static final int[] READ_TIMEOUT_SECS = {3, 8, 16, 34}; private static final int[] READ_TIMEOUT_SECS = {3, 8, 16, 34};
public static final int SOCKET_READ_TIMEOUT = 60000;
protected final HostAndPort server; protected final HostAndPort server;
protected final SocketFactory socketFactory; protected final SocketFactory socketFactory;
@ -107,8 +108,9 @@ public class TcpTransport implements Transport, Closeable {
try { try {
readingCondition.await(); readingCondition.await();
} catch(InterruptedException e) { } catch(InterruptedException e) {
//Restore interrupt status and continue //Restore interrupt status and break
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
break;
} }
} }
@ -192,6 +194,7 @@ public class TcpTransport implements Transport, Closeable {
public void connect() throws ServerException { public void connect() throws ServerException {
try { try {
socket = createSocket(); socket = createSocket();
socket.setSoTimeout(SOCKET_READ_TIMEOUT);
running = true; running = true;
} catch(SSLHandshakeException e) { } catch(SSLHandshakeException e) {
throw new TlsServerException(server, e); throw new TlsServerException(server, e);