Merge pull request #6211 from jmacxx/check_trade_init_app_close

Prevent shutdown if trade is in process of being taken.
This commit is contained in:
Christoph Atteneder 2022-05-18 09:38:32 +02:00 committed by GitHub
commit ecbd10d766
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 3 deletions

View File

@ -3080,6 +3080,10 @@ popup.info.shutDownWithOpenOffers=Bisq is being shut down, but there are open of
they will be re-published to the P2P network the next time you start Bisq.\n\n\
To keep your offers online, keep Bisq running and make sure this computer remains online too \
(i.e., make sure it doesn't go into standby mode...monitor standby is not a problem).
popup.info.shutDownWithTradeInit=Bisq is being shut down, but there are trades still being initialized. \n\n\
Specific trade affected: {0}\n\n\
If a trade is still in process of being initialized, shutting down can result in the trade missing some important state.\n\n\
Do not close Bisq if this trade has not had enough time to initialize correctly. One minute should be sufficient time.
popup.info.qubesOSSetupInfo=It appears you are running Bisq on Qubes OS. \n\n\
Please make sure your Bisq qube is setup according to our Setup Guide at [HYPERLINK:https://bisq.wiki/Running_Bisq_on_Qubes].
popup.info.firewallSetupInfo=It appears this machine blocks incoming Tor connections. \

View File

@ -31,6 +31,7 @@ import bisq.desktop.main.overlays.windows.SendAlertMessageWindow;
import bisq.desktop.main.overlays.windows.ShowWalletDataWindow;
import bisq.desktop.main.overlays.windows.WalletPasswordWindow;
import bisq.desktop.util.CssTheme;
import bisq.desktop.util.DisplayUtils;
import bisq.desktop.util.ImageUtil;
import bisq.core.btc.wallet.BtcWalletService;
@ -39,6 +40,8 @@ import bisq.core.dao.governance.voteresult.MissingDataRequestService;
import bisq.core.locale.Res;
import bisq.core.offer.OpenOffer;
import bisq.core.offer.OpenOfferManager;
import bisq.core.trade.TradeManager;
import bisq.core.trade.model.bisq_v1.Trade;
import bisq.core.user.Cookie;
import bisq.core.user.CookieKey;
import bisq.core.user.Preferences;
@ -73,9 +76,14 @@ import javafx.scene.layout.StackPane;
import javafx.geometry.Rectangle2D;
import javafx.geometry.BoundingBox;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import org.slf4j.LoggerFactory;
@ -356,6 +364,52 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
}
private void shutDownByUser() {
// two potential popup prompts to user before shutting down, each step can possibly abort the shutdown
shutDownByUserCheckTrades().thenAccept(shutdownStage1 -> {
if (shutdownStage1) {
shutDownByUserCheckOffers().thenAccept(shutdownStage2 -> {
if (shutdownStage2) {
stop();
}
});
}
});
}
private CompletableFuture<Boolean> shutDownByUserCheckTrades() {
final CompletableFuture<Boolean> asyncStatus = new CompletableFuture<>();
Instant fiveMinutesAgo = Instant.ofEpochSecond(Instant.now().getEpochSecond() - TimeUnit.MINUTES.toSeconds(5));
String tradeIdsWithOperationsPending = "";
for (Trade trade : injector.getInstance(TradeManager.class).getObservableList()) {
if (trade.getTradePhase().equals(Trade.Phase.TAKER_FEE_PUBLISHED) &&
new Date(trade.getTakeOfferDate()).toInstant().isAfter(fiveMinutesAgo)) {
String tradeDateString = DisplayUtils.formatDateTime(new Date(trade.getTakeOfferDate()));
tradeIdsWithOperationsPending += System.lineSeparator() +
Res.get("shared.tradeId") + ": " + trade.getShortId() + " " +
Res.get("shared.dateTime") + ": " + tradeDateString;
break;
}
}
if (tradeIdsWithOperationsPending.length() > 0) {
// We show a popup to inform user that some trades are still being initialised.
String key = "showInitTradeWarnPopupAtShutDown";
if (injector.getInstance(Preferences.class).showAgain(key) && !DevEnv.isDevMode()) {
new Popup().information(Res.get("popup.info.shutDownWithTradeInit", tradeIdsWithOperationsPending))
.dontShowAgainId(key)
.useShutDownButton()
.onAction(() -> asyncStatus.complete(true))
.closeButtonText(Res.get("shared.cancel"))
.onClose(() -> asyncStatus.complete(false))
.show();
}
} else {
asyncStatus.complete(true);
}
return asyncStatus;
}
private CompletableFuture<Boolean> shutDownByUserCheckOffers() {
final CompletableFuture<Boolean> asyncStatus = new CompletableFuture<>();
boolean hasOpenOffers = false;
for (OpenOffer openOffer : injector.getInstance(OpenOfferManager.class).getObservableList()) {
if (openOffer.getState().equals(OpenOffer.State.AVAILABLE)) {
@ -365,8 +419,8 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
}
if (!hasOpenOffers) {
// No open offers, so no need to show the popup.
stop();
return;
asyncStatus.complete(true);
return asyncStatus;
}
// We show a popup to inform user that open offers will be removed if Bisq is not running.
@ -375,11 +429,14 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
new Popup().information(Res.get("popup.info.shutDownWithOpenOffers"))
.dontShowAgainId(key)
.useShutDownButton()
.onAction(() -> asyncStatus.complete(true))
.closeButtonText(Res.get("shared.cancel"))
.onClose(() -> asyncStatus.complete(false))
.show();
} else {
stop();
asyncStatus.complete(true);
}
return asyncStatus;
}
// Used for debugging trade process