mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 07:07:43 +01:00
Merge pull request #4445 from chimp1984/restart-seednodes-deterministically
Use the index of a seed node address in the list of nodes at the
This commit is contained in:
commit
591d68a6fd
3 changed files with 116 additions and 18 deletions
|
@ -24,7 +24,9 @@ import bisq.core.btc.wallet.BtcWalletService;
|
||||||
import bisq.core.offer.OpenOfferManager;
|
import bisq.core.offer.OpenOfferManager;
|
||||||
import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
|
import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
|
||||||
|
|
||||||
|
import bisq.network.p2p.NodeAddress;
|
||||||
import bisq.network.p2p.P2PService;
|
import bisq.network.p2p.P2PService;
|
||||||
|
import bisq.network.p2p.seed.SeedNodeRepository;
|
||||||
|
|
||||||
import bisq.common.UserThread;
|
import bisq.common.UserThread;
|
||||||
import bisq.common.config.Config;
|
import bisq.common.config.Config;
|
||||||
|
@ -36,8 +38,15 @@ import bisq.common.util.RestartUtil;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -106,6 +115,62 @@ public abstract class ExecutableForAppWithP2p extends BisqExecutable implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void startShutDownInterval(GracefulShutDownHandler gracefulShutDownHandler) {
|
||||||
|
List<NodeAddress> seedNodeAddresses = new ArrayList<>(injector.getInstance(SeedNodeRepository.class).getSeedNodeAddresses());
|
||||||
|
seedNodeAddresses.sort(Comparator.comparing(NodeAddress::getFullAddress));
|
||||||
|
|
||||||
|
NodeAddress myAddress = injector.getInstance(P2PService.class).getNetworkNode().getNodeAddress();
|
||||||
|
int myIndex = -1;
|
||||||
|
for (int i = 0; i < seedNodeAddresses.size(); i++) {
|
||||||
|
if (seedNodeAddresses.get(i).equals(myAddress)) {
|
||||||
|
myIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myIndex == -1) {
|
||||||
|
log.warn("We did not find our node address in the seed nodes repository. " +
|
||||||
|
"We use a 24 hour delay after startup as shut down strategy." +
|
||||||
|
"myAddress={}, seedNodeAddresses={}",
|
||||||
|
myAddress, seedNodeAddresses);
|
||||||
|
|
||||||
|
UserThread.runPeriodically(() -> {
|
||||||
|
if (System.currentTimeMillis() - startTime > SHUTDOWN_INTERVAL) {
|
||||||
|
log.warn("\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" +
|
||||||
|
"Shut down as node was running longer as {} hours" +
|
||||||
|
"\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n",
|
||||||
|
SHUTDOWN_INTERVAL / 3600000);
|
||||||
|
|
||||||
|
shutDown(gracefulShutDownHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, CHECK_SHUTDOWN_SEC);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We interpret the value of myIndex as hour of day (0-23). That way we avoid the risk of a restart of
|
||||||
|
// multiple nodes around the same time in case it would be not deterministic.
|
||||||
|
|
||||||
|
// We wrap our periodic check in a delay of 2 hours to avoid that we get
|
||||||
|
// triggered multiple times after a restart while being in the same hour. It can be that we miss our target
|
||||||
|
// hour during that delay but that is not considered problematic, the seed would just restart a bit longer than
|
||||||
|
// 24 hours.
|
||||||
|
int target = myIndex;
|
||||||
|
UserThread.runAfter(() -> {
|
||||||
|
// We check every hour if we are in the target hour.
|
||||||
|
UserThread.runPeriodically(() -> {
|
||||||
|
int currentHour = ZonedDateTime.ofInstant(Instant.now(), ZoneId.of("GMT0")).getHour();
|
||||||
|
if (currentHour == target) {
|
||||||
|
log.warn("\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" +
|
||||||
|
"Shut down node at hour {}" +
|
||||||
|
"\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n", target);
|
||||||
|
shutDown(gracefulShutDownHandler);
|
||||||
|
}
|
||||||
|
}, TimeUnit.MINUTES.toSeconds(10));
|
||||||
|
}, TimeUnit.HOURS.toSeconds(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// UncaughtExceptionHandler implementation
|
// UncaughtExceptionHandler implementation
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -128,20 +193,6 @@ public abstract class ExecutableForAppWithP2p extends BisqExecutable implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void startShutDownInterval(GracefulShutDownHandler gracefulShutDownHandler) {
|
|
||||||
UserThread.runPeriodically(() -> {
|
|
||||||
if (System.currentTimeMillis() - startTime > SHUTDOWN_INTERVAL) {
|
|
||||||
log.warn("\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" +
|
|
||||||
"Shut down as node was running longer as {} hours" +
|
|
||||||
"\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n",
|
|
||||||
SHUTDOWN_INTERVAL / 3600000);
|
|
||||||
|
|
||||||
shutDown(gracefulShutDownHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
}, CHECK_SHUTDOWN_SEC);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void checkMemory(Config config, GracefulShutDownHandler gracefulShutDownHandler) {
|
protected void checkMemory(Config config, GracefulShutDownHandler gracefulShutDownHandler) {
|
||||||
int maxMemory = config.maxMemory;
|
int maxMemory = config.maxMemory;
|
||||||
UserThread.runPeriodically(() -> {
|
UserThread.runPeriodically(() -> {
|
||||||
|
|
|
@ -55,6 +55,7 @@ class RequestDataHandler implements MessageListener {
|
||||||
private static final long TIMEOUT = 180;
|
private static final long TIMEOUT = 180;
|
||||||
|
|
||||||
private NodeAddress peersNodeAddress;
|
private NodeAddress peersNodeAddress;
|
||||||
|
private String getDataRequestType;
|
||||||
/*
|
/*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -138,7 +139,8 @@ class RequestDataHandler implements MessageListener {
|
||||||
TIMEOUT);
|
TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("We send a {} to peer {}. ", getDataRequest.getClass().getSimpleName(), nodeAddress);
|
getDataRequestType = getDataRequest.getClass().getSimpleName();
|
||||||
|
log.info("We send a {} to peer {}. ", getDataRequestType, nodeAddress);
|
||||||
networkNode.addMessageListener(this);
|
networkNode.addMessageListener(this);
|
||||||
SettableFuture<Connection> future = networkNode.sendMessage(nodeAddress, getDataRequest);
|
SettableFuture<Connection> future = networkNode.sendMessage(nodeAddress, getDataRequest);
|
||||||
//noinspection UnstableApiUsage
|
//noinspection UnstableApiUsage
|
||||||
|
@ -259,8 +261,9 @@ class RequestDataHandler implements MessageListener {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("\n#################################################################\n");
|
sb.append("\n#################################################################\n");
|
||||||
sb.append("Connected to node: " + peersNodeAddress.getFullAddress() + "\n");
|
sb.append("Connected to node: " + peersNodeAddress.getFullAddress() + "\n");
|
||||||
final int items = dataSet.size() + persistableNetworkPayloadSet.size();
|
int items = dataSet.size() + persistableNetworkPayloadSet.size();
|
||||||
sb.append("Received ").append(items).append(" instances\n");
|
sb.append("Received ").append(items).append(" instances from a ")
|
||||||
|
.append(getDataRequestType).append("\n");
|
||||||
payloadByClassName.forEach((key, value) -> sb.append(key)
|
payloadByClassName.forEach((key, value) -> sb.append(key)
|
||||||
.append(": ")
|
.append(": ")
|
||||||
.append(value.size())
|
.append(value.size())
|
||||||
|
|
|
@ -20,6 +20,9 @@ package bisq.seednode;
|
||||||
import bisq.core.app.misc.ExecutableForAppWithP2p;
|
import bisq.core.app.misc.ExecutableForAppWithP2p;
|
||||||
import bisq.core.app.misc.ModuleForAppWithP2p;
|
import bisq.core.app.misc.ModuleForAppWithP2p;
|
||||||
|
|
||||||
|
import bisq.network.p2p.P2PService;
|
||||||
|
import bisq.network.p2p.P2PServiceListener;
|
||||||
|
|
||||||
import bisq.common.UserThread;
|
import bisq.common.UserThread;
|
||||||
import bisq.common.app.AppModule;
|
import bisq.common.app.AppModule;
|
||||||
import bisq.common.app.Capabilities;
|
import bisq.common.app.Capabilities;
|
||||||
|
@ -47,7 +50,6 @@ public class SeedNodeMain extends ExecutableForAppWithP2p {
|
||||||
super.doExecute();
|
super.doExecute();
|
||||||
|
|
||||||
checkMemory(config, this);
|
checkMemory(config, this);
|
||||||
startShutDownInterval(this);
|
|
||||||
CommonSetup.setup(this);
|
CommonSetup.setup(this);
|
||||||
|
|
||||||
keepRunning();
|
keepRunning();
|
||||||
|
@ -95,5 +97,47 @@ public class SeedNodeMain extends ExecutableForAppWithP2p {
|
||||||
@Override
|
@Override
|
||||||
protected void startApplication() {
|
protected void startApplication() {
|
||||||
seedNode.startApplication();
|
seedNode.startApplication();
|
||||||
|
|
||||||
|
injector.getInstance(P2PService.class).addP2PServiceListener(new P2PServiceListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataReceived() {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNoSeedNodeAvailable() {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNoPeersAvailable() {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdatedDataReceived() {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTorNodeReady() {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHiddenServicePublished() {
|
||||||
|
startShutDownInterval(SeedNodeMain.this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSetupFailed(Throwable throwable) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestCustomBridges() {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue