mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-08-03 20:24:24 -04:00
Handle offer removal on disconnects
This commit is contained in:
parent
cb236f65fb
commit
58bb1868a3
29 changed files with 532 additions and 385 deletions
|
@ -20,7 +20,7 @@ package io.bitsquare.alert;
|
|||
import com.google.inject.Inject;
|
||||
import io.bitsquare.common.crypto.KeyRing;
|
||||
import io.bitsquare.p2p.storage.HashMapChangedListener;
|
||||
import io.bitsquare.p2p.storage.ProtectedData;
|
||||
import io.bitsquare.p2p.storage.data.ProtectedData;
|
||||
import io.bitsquare.user.User;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
|
|
|
@ -30,7 +30,7 @@ import io.bitsquare.p2p.BootstrapListener;
|
|||
import io.bitsquare.p2p.NodeAddress;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
import io.bitsquare.p2p.storage.HashMapChangedListener;
|
||||
import io.bitsquare.p2p.storage.ProtectedData;
|
||||
import io.bitsquare.p2p.storage.data.ProtectedData;
|
||||
import io.bitsquare.user.User;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableMap;
|
||||
|
|
|
@ -25,7 +25,7 @@ import io.bitsquare.common.handlers.ResultHandler;
|
|||
import io.bitsquare.common.util.JsonExclude;
|
||||
import io.bitsquare.locale.Country;
|
||||
import io.bitsquare.p2p.NodeAddress;
|
||||
import io.bitsquare.p2p.storage.messages.RequiresLiveOwnerData;
|
||||
import io.bitsquare.p2p.storage.messages.RequiresOwnerIsOnlineMessage;
|
||||
import io.bitsquare.p2p.storage.messages.StorageMessage;
|
||||
import io.bitsquare.payment.PaymentMethod;
|
||||
import io.bitsquare.trade.protocol.availability.OfferAvailabilityModel;
|
||||
|
@ -47,7 +47,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public final class Offer implements StorageMessage, RequiresLiveOwnerData {
|
||||
public final class Offer implements StorageMessage, RequiresOwnerIsOnlineMessage {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
@JsonExclude
|
||||
private static final long serialVersionUID = Version.P2P_NETWORK_VERSION;
|
||||
|
@ -55,7 +55,7 @@ public final class Offer implements StorageMessage, RequiresLiveOwnerData {
|
|||
private static final Logger log = LoggerFactory.getLogger(Offer.class);
|
||||
|
||||
public static final long TTL = TimeUnit.SECONDS.toMillis(60);
|
||||
|
||||
|
||||
public final static String TAC_OFFERER = "When placing that offer I accept that anyone who fulfills my conditions can " +
|
||||
"take that offer.";
|
||||
public static final String TAC_TAKER = "With taking the offer I commit to the trade conditions as defined.";
|
||||
|
|
|
@ -21,7 +21,7 @@ import io.bitsquare.common.handlers.ErrorMessageHandler;
|
|||
import io.bitsquare.common.handlers.ResultHandler;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
import io.bitsquare.p2p.storage.HashMapChangedListener;
|
||||
import io.bitsquare.p2p.storage.ProtectedData;
|
||||
import io.bitsquare.p2p.storage.data.ProtectedData;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -84,21 +84,27 @@ public class OfferBookService {
|
|||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
public void republishOffers(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
doAddOffer(offer, resultHandler, errorMessageHandler, true);
|
||||
}
|
||||
|
||||
public void addOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
doAddOffer(offer, resultHandler, errorMessageHandler, false);
|
||||
}
|
||||
|
||||
public void republishOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
doAddOffer(offer, resultHandler, errorMessageHandler, true);
|
||||
public void doAddOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler, boolean forceBroadcast) {
|
||||
boolean result = p2PService.addData(offer, forceBroadcast);
|
||||
if (result) {
|
||||
log.trace("Add offer to network was successful. Offer ID = " + offer.getId());
|
||||
resultHandler.handleResult();
|
||||
} else {
|
||||
errorMessageHandler.handleErrorMessage("Add offer failed");
|
||||
}
|
||||
}
|
||||
|
||||
private void doAddOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler, boolean rePublish) {
|
||||
boolean result;
|
||||
if (rePublish)
|
||||
result = p2PService.republishData(offer);
|
||||
else
|
||||
result = p2PService.addData(offer);
|
||||
|
||||
public void refreshOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
boolean result = p2PService.refreshTTL(offer);
|
||||
if (result) {
|
||||
log.trace("Add offer to network was successful. Offer ID = " + offer.getId());
|
||||
resultHandler.handleResult();
|
||||
|
|
|
@ -30,6 +30,10 @@ import io.bitsquare.p2p.Message;
|
|||
import io.bitsquare.p2p.NodeAddress;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
import io.bitsquare.p2p.messaging.SendDirectMessageListener;
|
||||
import io.bitsquare.p2p.network.CloseConnectionReason;
|
||||
import io.bitsquare.p2p.network.Connection;
|
||||
import io.bitsquare.p2p.network.ConnectionListener;
|
||||
import io.bitsquare.p2p.network.NetworkNode;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import io.bitsquare.trade.TradableList;
|
||||
import io.bitsquare.trade.closed.ClosedTradableManager;
|
||||
|
@ -70,6 +74,10 @@ public class OpenOfferManager {
|
|||
private boolean shutDownRequested;
|
||||
private BootstrapListener bootstrapListener;
|
||||
private final Timer timer = new Timer();
|
||||
private Timer republishOffersTime;
|
||||
private boolean firstTimeConnection;
|
||||
private boolean allowRefreshOffers;
|
||||
private boolean lostAllConnections;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -112,6 +120,44 @@ public class OpenOfferManager {
|
|||
if (message instanceof OfferAvailabilityRequest)
|
||||
handleOfferAvailabilityRequest((OfferAvailabilityRequest) message, peersNodeAddress);
|
||||
});
|
||||
|
||||
NetworkNode networkNode = p2PService.getNetworkNode();
|
||||
networkNode.addConnectionListener(new ConnectionListener() {
|
||||
@Override
|
||||
public void onConnection(Connection connection) {
|
||||
log.error("ConnectionListener onConnection size " + networkNode.getAllConnections().size());
|
||||
log.error("ConnectionListener onConnection lostAllConnections " + lostAllConnections);
|
||||
log.error("ConnectionListener onConnection allowRefreshOffers " + allowRefreshOffers);
|
||||
log.error("ConnectionListener onConnection republishOffersTime " + republishOffersTime);
|
||||
if (lostAllConnections) {
|
||||
lostAllConnections = false;
|
||||
allowRefreshOffers = false;
|
||||
|
||||
// We repeat a rePublishOffers call after 10 seconds if we have more than 3 peers
|
||||
if (republishOffersTime == null) {
|
||||
republishOffersTime = UserThread.runAfter(() -> {
|
||||
if (networkNode.getAllConnections().size() > 3)
|
||||
republishOffers();
|
||||
|
||||
allowRefreshOffers = true;
|
||||
republishOffersTime = null;
|
||||
}, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnect(CloseConnectionReason closeConnectionReason, Connection connection) {
|
||||
log.error("ConnectionListener onDisconnect size " + networkNode.getAllConnections().size());
|
||||
lostAllConnections = networkNode.getAllConnections().isEmpty();
|
||||
if (lostAllConnections)
|
||||
allowRefreshOffers = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -132,53 +178,75 @@ public class OpenOfferManager {
|
|||
bootstrapListener = new BootstrapListener() {
|
||||
@Override
|
||||
public void onBootstrapComplete() {
|
||||
startRePublishThread();
|
||||
onBootstrapped();
|
||||
}
|
||||
};
|
||||
p2PService.addP2PServiceListener(bootstrapListener);
|
||||
|
||||
} else {
|
||||
startRePublishThread();
|
||||
onBootstrapped();
|
||||
}
|
||||
}
|
||||
|
||||
private void startRePublishThread() {
|
||||
private void onBootstrapped() {
|
||||
if (bootstrapListener != null)
|
||||
p2PService.removeP2PServiceListener(bootstrapListener);
|
||||
|
||||
// republish sufficiently before offer would expire
|
||||
republishOffers();
|
||||
startRefreshOffersThread();
|
||||
|
||||
//TODO should not be needed
|
||||
// startRepublishOffersThread();
|
||||
}
|
||||
|
||||
private void startRefreshOffersThread() {
|
||||
allowRefreshOffers = true;
|
||||
// refresh sufficiently before offer would expire
|
||||
long period = (long) (Offer.TTL * 0.7);
|
||||
TimerTask timerTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
UserThread.execute(OpenOfferManager.this::rePublishOffers);
|
||||
UserThread.execute(OpenOfferManager.this::refreshOffers);
|
||||
}
|
||||
};
|
||||
timer.scheduleAtFixedRate(timerTask, 500, period);
|
||||
|
||||
p2PService.getNumConnectedPeers().addListener((observable, oldValue, newValue) -> {
|
||||
if ((int) oldValue == 0 && (int) newValue > 0) {
|
||||
rePublishOffers();
|
||||
|
||||
// We repeat a rePublishOffers call after 10 seconds if we have more than 3 peers
|
||||
UserThread.runAfter(() -> {
|
||||
if (p2PService.getNumConnectedPeers().get() > 3)
|
||||
rePublishOffers();
|
||||
}, 10);
|
||||
}
|
||||
});
|
||||
timer.scheduleAtFixedRate(timerTask, period, period);
|
||||
}
|
||||
|
||||
private void rePublishOffers() {
|
||||
|
||||
private void startRepublishOffersThread() {
|
||||
long period = Offer.TTL * 10;
|
||||
TimerTask timerTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
UserThread.execute(OpenOfferManager.this::republishOffers);
|
||||
}
|
||||
};
|
||||
timer.scheduleAtFixedRate(timerTask, period, period);
|
||||
}
|
||||
|
||||
private void republishOffers() {
|
||||
log.error("republishOffers ");
|
||||
Log.traceCall("Number of offer for republish: " + openOffers.size());
|
||||
for (OpenOffer openOffer : openOffers) {
|
||||
offerBookService.republishOffer(openOffer.getOffer(),
|
||||
offerBookService.republishOffers(openOffer.getOffer(),
|
||||
() -> log.debug("Successful added offer to P2P network"),
|
||||
errorMessage -> log.error("Add offer to P2P network failed. " + errorMessage));
|
||||
openOffer.setStorage(openOffersStorage);
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshOffers() {
|
||||
if (allowRefreshOffers) {
|
||||
Log.traceCall("Number of offer for refresh: " + openOffers.size());
|
||||
for (OpenOffer openOffer : openOffers) {
|
||||
offerBookService.refreshOffer(openOffer.getOffer(),
|
||||
() -> log.debug("Successful refreshed TTL for offer"),
|
||||
errorMessage -> log.error("Refresh TTL for offer failed. " + errorMessage));
|
||||
openOffer.setStorage(openOffersStorage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public void shutDown() {
|
||||
shutDown(null);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue