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 String LOADING_TRANSACTIONS_MESSAGE = "Loading wallet, select Transactions tab to view...";
public static final String CONNECTION_FAILED_PREFIX = "Connection failed: ";
public static final String TRYING_ANOTHER_SERVER_MESSAGE = "trying another server...";
@FXML
private MenuItem saveTransaction;
@ -1539,8 +1540,10 @@ public class AppController implements Initializable {
@Subscribe
public void connectionStart(ConnectionStartEvent event) {
if(!statusBar.getText().contains(TRYING_ANOTHER_SERVER_MESSAGE)) {
statusUpdated(new StatusEvent(event.getStatus(), 120));
}
}
@Subscribe
public void connectionFailed(ConnectionFailedEvent event) {
@ -1558,12 +1561,15 @@ public class AppController implements Initializable {
@Subscribe
public void disconnection(DisconnectionEvent event) {
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"));
}
if(statusTimeline == null || statusTimeline.getStatus() != Animation.Status.RUNNING) {
statusBar.setProgress(0);
}
for(Wallet wallet : getOpenWallets().keySet()) {
tabLabelStopAnimation(wallet);
}
}
@Subscribe
@ -1620,6 +1626,9 @@ public class AppController implements Initializable {
public void walletHistoryFailed(WalletHistoryFailedEvent event) {
walletHistoryFinished(new WalletHistoryFinishedEvent(event.getWallet()));
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

View file

@ -250,8 +250,7 @@ public class AppServices {
onlineProperty.addListener(onlineServicesListener);
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().setPublicElectrumServer(otherServers.get(new Random().nextInt(otherServers.size())));
Config.get().changePublicServer();
connectionService.setPeriod(Duration.seconds(PUBLIC_SERVER_RETRY_PERIOD_SECS));
}
@ -715,4 +714,14 @@ public class AppServices {
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.lang.reflect.Type;
import java.util.Arrays;
import java.util.Currency;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
public class Config {
private static final Logger log = LoggerFactory.getLogger(Config.class);
@ -333,6 +336,11 @@ public class Config {
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() {
return coreServer;
}

View file

@ -19,7 +19,7 @@ import java.util.concurrent.atomic.AtomicLong;
public class SimpleElectrumServerRpc implements ElectrumServerRpc {
private static final Logger log = LoggerFactory.getLogger(SimpleElectrumServerRpc.class);
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 final AtomicLong idCounter = new AtomicLong();

View file

@ -24,6 +24,7 @@ public class TcpTransport implements Transport, Closeable {
public static final int DEFAULT_PORT = 50001;
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 SocketFactory socketFactory;
@ -107,8 +108,9 @@ public class TcpTransport implements Transport, Closeable {
try {
readingCondition.await();
} catch(InterruptedException e) {
//Restore interrupt status and continue
//Restore interrupt status and break
Thread.currentThread().interrupt();
break;
}
}
@ -192,6 +194,7 @@ public class TcpTransport implements Transport, Closeable {
public void connect() throws ServerException {
try {
socket = createSocket();
socket.setSoTimeout(SOCKET_READ_TIMEOUT);
running = true;
} catch(SSLHandshakeException e) {
throw new TlsServerException(server, e);