mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Merge pull request #4950 from chimp1984/improve-offer-publishing
Improve offer publishing
This commit is contained in:
commit
94cf02303e
@ -49,6 +49,7 @@ import bisq.network.p2p.DecryptedMessageWithPubKey;
|
|||||||
import bisq.network.p2p.NodeAddress;
|
import bisq.network.p2p.NodeAddress;
|
||||||
import bisq.network.p2p.P2PService;
|
import bisq.network.p2p.P2PService;
|
||||||
import bisq.network.p2p.SendDirectMessageListener;
|
import bisq.network.p2p.SendDirectMessageListener;
|
||||||
|
import bisq.network.p2p.peers.Broadcaster;
|
||||||
import bisq.network.p2p.peers.PeerManager;
|
import bisq.network.p2p.peers.PeerManager;
|
||||||
|
|
||||||
import bisq.common.Timer;
|
import bisq.common.Timer;
|
||||||
@ -117,6 +118,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||||||
private final RefundAgentManager refundAgentManager;
|
private final RefundAgentManager refundAgentManager;
|
||||||
private final DaoFacade daoFacade;
|
private final DaoFacade daoFacade;
|
||||||
private final FilterManager filterManager;
|
private final FilterManager filterManager;
|
||||||
|
private final Broadcaster broadcaster;
|
||||||
private final PersistenceManager<TradableList<OpenOffer>> persistenceManager;
|
private final PersistenceManager<TradableList<OpenOffer>> persistenceManager;
|
||||||
private final Map<String, OpenOffer> offersToBeEdited = new HashMap<>();
|
private final Map<String, OpenOffer> offersToBeEdited = new HashMap<>();
|
||||||
private final TradableList<OpenOffer> openOffers = new TradableList<>();
|
private final TradableList<OpenOffer> openOffers = new TradableList<>();
|
||||||
@ -148,6 +150,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||||||
RefundAgentManager refundAgentManager,
|
RefundAgentManager refundAgentManager,
|
||||||
DaoFacade daoFacade,
|
DaoFacade daoFacade,
|
||||||
FilterManager filterManager,
|
FilterManager filterManager,
|
||||||
|
Broadcaster broadcaster,
|
||||||
PersistenceManager<TradableList<OpenOffer>> persistenceManager) {
|
PersistenceManager<TradableList<OpenOffer>> persistenceManager) {
|
||||||
this.createOfferService = createOfferService;
|
this.createOfferService = createOfferService;
|
||||||
this.keyRing = keyRing;
|
this.keyRing = keyRing;
|
||||||
@ -166,6 +169,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||||||
this.refundAgentManager = refundAgentManager;
|
this.refundAgentManager = refundAgentManager;
|
||||||
this.daoFacade = daoFacade;
|
this.daoFacade = daoFacade;
|
||||||
this.filterManager = filterManager;
|
this.filterManager = filterManager;
|
||||||
|
this.broadcaster = broadcaster;
|
||||||
this.persistenceManager = persistenceManager;
|
this.persistenceManager = persistenceManager;
|
||||||
|
|
||||||
this.persistenceManager.initialize(openOffers, "OpenOffers", PersistenceManager.Source.PRIVATE);
|
this.persistenceManager.initialize(openOffers, "OpenOffers", PersistenceManager.Source.PRIVATE);
|
||||||
@ -214,10 +218,6 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void shutDown() {
|
|
||||||
shutDown(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void shutDown(@Nullable Runnable completeHandler) {
|
public void shutDown(@Nullable Runnable completeHandler) {
|
||||||
stopped = true;
|
stopped = true;
|
||||||
p2PService.getPeerManager().removeListener(this);
|
p2PService.getPeerManager().removeListener(this);
|
||||||
@ -235,6 +235,11 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||||||
UserThread.execute(() -> openOffers.forEach(
|
UserThread.execute(() -> openOffers.forEach(
|
||||||
openOffer -> offerBookService.removeOfferAtShutDown(openOffer.getOffer().getOfferPayload())
|
openOffer -> offerBookService.removeOfferAtShutDown(openOffer.getOffer().getOfferPayload())
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// Force broadcaster to send out immediately, otherwise we could have a 2 sec delay until the
|
||||||
|
// bundled messages sent out.
|
||||||
|
broadcaster.flush();
|
||||||
|
|
||||||
if (completeHandler != null) {
|
if (completeHandler != null) {
|
||||||
// For typical number of offers we are tolerant with delay to give enough time to broadcast.
|
// For typical number of offers we are tolerant with delay to give enough time to broadcast.
|
||||||
// If number of offers is very high we limit to 3 sec. to not delay other shutdown routines.
|
// If number of offers is very high we limit to 3 sec. to not delay other shutdown routines.
|
||||||
@ -873,41 +878,53 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void republishOffers() {
|
private void republishOffers() {
|
||||||
int size = openOffers.size();
|
if (stopped) {
|
||||||
final ArrayList<OpenOffer> openOffersList = new ArrayList<>(openOffers.getList());
|
return;
|
||||||
if (!stopped) {
|
}
|
||||||
stopPeriodicRefreshOffersTimer();
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
// we delay to avoid reaching throttle limits
|
|
||||||
|
|
||||||
long delay = 700;
|
stopPeriodicRefreshOffersTimer();
|
||||||
final long minDelay = (i + 1) * delay;
|
|
||||||
final long maxDelay = (i + 2) * delay;
|
|
||||||
final OpenOffer openOffer = openOffersList.get(i);
|
|
||||||
UserThread.runAfterRandomDelay(() -> {
|
|
||||||
if (openOffers.contains(openOffer)) {
|
|
||||||
String id = openOffer.getId();
|
|
||||||
if (id != null && !openOffer.isDeactivated())
|
|
||||||
republishOffer(openOffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
}, minDelay, maxDelay, TimeUnit.MILLISECONDS);
|
List<OpenOffer> openOffersList = new ArrayList<>(openOffers.getList());
|
||||||
}
|
processListForRepublishOffers(openOffersList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processListForRepublishOffers(List<OpenOffer> list) {
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenOffer openOffer = list.remove(0);
|
||||||
|
if (openOffers.contains(openOffer) && !openOffer.isDeactivated()) {
|
||||||
|
// TODO It is not clear yet if it is better for the node and the network to send out all add offer
|
||||||
|
// messages in one go or to spread it over a delay. With power users who have 100-200 offers that can have
|
||||||
|
// some significant impact to user experience and the network
|
||||||
|
republishOffer(openOffer, () -> processListForRepublishOffers(list));
|
||||||
|
|
||||||
|
/* republishOffer(openOffer,
|
||||||
|
() -> UserThread.runAfter(() -> processListForRepublishOffers(list),
|
||||||
|
30, TimeUnit.MILLISECONDS));*/
|
||||||
} else {
|
} else {
|
||||||
log.debug("We have stopped already. We ignore that republishOffers call.");
|
// If the offer was removed in the meantime or if its deactivated we skip and call
|
||||||
|
// processListForRepublishOffers again with the list where we removed the offer already.
|
||||||
|
processListForRepublishOffers(list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void republishOffer(OpenOffer openOffer) {
|
private void republishOffer(OpenOffer openOffer) {
|
||||||
|
republishOffer(openOffer, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void republishOffer(OpenOffer openOffer, @Nullable Runnable completeHandler) {
|
||||||
offerBookService.addOffer(openOffer.getOffer(),
|
offerBookService.addOffer(openOffer.getOffer(),
|
||||||
() -> {
|
() -> {
|
||||||
if (!stopped) {
|
if (!stopped) {
|
||||||
log.debug("Successfully added offer to P2P network.");
|
|
||||||
// Refresh means we send only the data needed to refresh the TTL (hash, signature and sequence no.)
|
// Refresh means we send only the data needed to refresh the TTL (hash, signature and sequence no.)
|
||||||
if (periodicRefreshOffersTimer == null)
|
if (periodicRefreshOffersTimer == null) {
|
||||||
startPeriodicRefreshOffersTimer();
|
startPeriodicRefreshOffersTimer();
|
||||||
} else {
|
}
|
||||||
log.debug("We have stopped already. We ignore that offerBookService.republishOffers.onSuccess call.");
|
if (completeHandler != null) {
|
||||||
|
completeHandler.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
errorMessage -> {
|
errorMessage -> {
|
||||||
@ -916,26 +933,25 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||||||
stopRetryRepublishOffersTimer();
|
stopRetryRepublishOffersTimer();
|
||||||
retryRepublishOffersTimer = UserThread.runAfter(OpenOfferManager.this::republishOffers,
|
retryRepublishOffersTimer = UserThread.runAfter(OpenOfferManager.this::republishOffers,
|
||||||
RETRY_REPUBLISH_DELAY_SEC);
|
RETRY_REPUBLISH_DELAY_SEC);
|
||||||
} else {
|
|
||||||
log.debug("We have stopped already. We ignore that offerBookService.republishOffers.onFault call.");
|
if (completeHandler != null) {
|
||||||
|
completeHandler.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startPeriodicRepublishOffersTimer() {
|
private void startPeriodicRepublishOffersTimer() {
|
||||||
stopped = false;
|
stopped = false;
|
||||||
if (periodicRepublishOffersTimer == null)
|
if (periodicRepublishOffersTimer == null) {
|
||||||
periodicRepublishOffersTimer = UserThread.runPeriodically(() -> {
|
periodicRepublishOffersTimer = UserThread.runPeriodically(() -> {
|
||||||
if (!stopped) {
|
if (!stopped) {
|
||||||
republishOffers();
|
republishOffers();
|
||||||
} else {
|
|
||||||
log.debug("We have stopped already. We ignore that periodicRepublishOffersTimer.run call.");
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
REPUBLISH_INTERVAL_MS,
|
REPUBLISH_INTERVAL_MS,
|
||||||
TimeUnit.MILLISECONDS);
|
TimeUnit.MILLISECONDS);
|
||||||
else
|
}
|
||||||
log.trace("periodicRepublishOffersTimer already stated");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startPeriodicRefreshOffersTimer() {
|
private void startPeriodicRefreshOffersTimer() {
|
||||||
|
@ -49,7 +49,7 @@ public class OpenOfferManagerTest {
|
|||||||
final OpenOfferManager manager = new OpenOfferManager(null, null, null, p2PService,
|
final OpenOfferManager manager = new OpenOfferManager(null, null, null, p2PService,
|
||||||
null, null, null, offerBookService,
|
null, null, null, offerBookService,
|
||||||
null, null, null,
|
null, null, null,
|
||||||
null, null, null, null, null, null,
|
null, null, null, null, null, null, null,
|
||||||
persistenceManager);
|
persistenceManager);
|
||||||
|
|
||||||
AtomicBoolean startEditOfferSuccessful = new AtomicBoolean(false);
|
AtomicBoolean startEditOfferSuccessful = new AtomicBoolean(false);
|
||||||
@ -81,7 +81,7 @@ public class OpenOfferManagerTest {
|
|||||||
final OpenOfferManager manager = new OpenOfferManager(null, null, null, p2PService,
|
final OpenOfferManager manager = new OpenOfferManager(null, null, null, p2PService,
|
||||||
null, null, null, offerBookService,
|
null, null, null, offerBookService,
|
||||||
null, null, null,
|
null, null, null,
|
||||||
null, null, null, null, null, null,
|
null, null, null, null, null, null, null,
|
||||||
persistenceManager);
|
persistenceManager);
|
||||||
|
|
||||||
AtomicBoolean startEditOfferSuccessful = new AtomicBoolean(false);
|
AtomicBoolean startEditOfferSuccessful = new AtomicBoolean(false);
|
||||||
@ -106,7 +106,7 @@ public class OpenOfferManagerTest {
|
|||||||
final OpenOfferManager manager = new OpenOfferManager(null, null, null, p2PService,
|
final OpenOfferManager manager = new OpenOfferManager(null, null, null, p2PService,
|
||||||
null, null, null, offerBookService,
|
null, null, null, offerBookService,
|
||||||
null, null, null,
|
null, null, null,
|
||||||
null, null, null, null, null, null,
|
null, null, null, null, null, null, null,
|
||||||
persistenceManager);
|
persistenceManager);
|
||||||
|
|
||||||
AtomicBoolean startEditOfferSuccessful = new AtomicBoolean(false);
|
AtomicBoolean startEditOfferSuccessful = new AtomicBoolean(false);
|
||||||
|
@ -73,6 +73,10 @@ public class Broadcaster implements BroadcastHandler.ResultHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void flush() {
|
||||||
|
maybeBroadcastBundle();
|
||||||
|
}
|
||||||
|
|
||||||
private void doShutDown() {
|
private void doShutDown() {
|
||||||
broadcastHandlers.forEach(BroadcastHandler::cancel);
|
broadcastHandlers.forEach(BroadcastHandler::cancel);
|
||||||
if (timer != null) {
|
if (timer != null) {
|
||||||
|
Loading…
Reference in New Issue
Block a user