Warn at shutdown if Dispute message is pending.

This commit is contained in:
jmacxx 2022-10-11 17:54:07 -05:00
parent f7f78a1624
commit b35e316cdc
No known key found for this signature in database
GPG Key ID: 155297BABFE94A1B
3 changed files with 59 additions and 1 deletions

View File

@ -95,6 +95,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
private final Config config; private final Config config;
private final PriceFeedService priceFeedService; private final PriceFeedService priceFeedService;
protected final DaoFacade daoFacade; protected final DaoFacade daoFacade;
protected String pendingOutgoingMessage;
@Getter @Getter
protected final ObservableList<TradeDataValidation.ValidationException> validationExceptions = protected final ObservableList<TradeDataValidation.ValidationException> validationExceptions =
@ -132,6 +133,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
this.disputeListService = disputeListService; this.disputeListService = disputeListService;
this.config = config; this.config = config;
this.priceFeedService = priceFeedService; this.priceFeedService = priceFeedService;
clearPendingMessage();
} }
@ -502,6 +504,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
openNewDisputeMessage.getUid(), openNewDisputeMessage.getUid(),
chatMessage.getUid()); chatMessage.getUid());
recordPendingMessage(openNewDisputeMessage.getClass().getSimpleName());
mailboxMessageService.sendEncryptedMailboxMessage(agentNodeAddress, mailboxMessageService.sendEncryptedMailboxMessage(agentNodeAddress,
dispute.getAgentPubKeyRing(), dispute.getAgentPubKeyRing(),
openNewDisputeMessage, openNewDisputeMessage,
@ -514,6 +517,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
openNewDisputeMessage.getTradeId(), openNewDisputeMessage.getUid(), openNewDisputeMessage.getTradeId(), openNewDisputeMessage.getUid(),
chatMessage.getUid()); chatMessage.getUid());
clearPendingMessage();
// We use the chatMessage wrapped inside the openNewDisputeMessage for // We use the chatMessage wrapped inside the openNewDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg // the state, as that is displayed to the user and we only persist that msg
chatMessage.setArrived(true); chatMessage.setArrived(true);
@ -529,6 +533,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
openNewDisputeMessage.getTradeId(), openNewDisputeMessage.getUid(), openNewDisputeMessage.getTradeId(), openNewDisputeMessage.getUid(),
chatMessage.getUid()); chatMessage.getUid());
clearPendingMessage();
// We use the chatMessage wrapped inside the openNewDisputeMessage for // We use the chatMessage wrapped inside the openNewDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg // the state, as that is displayed to the user and we only persist that msg
chatMessage.setStoredInMailbox(true); chatMessage.setStoredInMailbox(true);
@ -544,6 +549,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
openNewDisputeMessage.getTradeId(), openNewDisputeMessage.getUid(), openNewDisputeMessage.getTradeId(), openNewDisputeMessage.getUid(),
chatMessage.getUid(), errorMessage); chatMessage.getUid(), errorMessage);
clearPendingMessage();
// We use the chatMessage wrapped inside the openNewDisputeMessage for // We use the chatMessage wrapped inside the openNewDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg // the state, as that is displayed to the user and we only persist that msg
chatMessage.setSendMessageError(errorMessage); chatMessage.setSendMessageError(errorMessage);
@ -650,6 +656,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
peerOpenedDisputeMessage.getTradeId(), peerOpenedDisputeMessage.getUid(), peerOpenedDisputeMessage.getTradeId(), peerOpenedDisputeMessage.getUid(),
chatMessage.getUid()); chatMessage.getUid());
recordPendingMessage(peerOpenedDisputeMessage.getClass().getSimpleName());
mailboxMessageService.sendEncryptedMailboxMessage(peersNodeAddress, mailboxMessageService.sendEncryptedMailboxMessage(peersNodeAddress,
peersPubKeyRing, peersPubKeyRing,
peerOpenedDisputeMessage, peerOpenedDisputeMessage,
@ -662,6 +669,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
peerOpenedDisputeMessage.getTradeId(), peerOpenedDisputeMessage.getUid(), peerOpenedDisputeMessage.getTradeId(), peerOpenedDisputeMessage.getUid(),
chatMessage.getUid()); chatMessage.getUid());
clearPendingMessage();
// We use the chatMessage wrapped inside the peerOpenedDisputeMessage for // We use the chatMessage wrapped inside the peerOpenedDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg // the state, as that is displayed to the user and we only persist that msg
chatMessage.setArrived(true); chatMessage.setArrived(true);
@ -676,6 +684,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
peerOpenedDisputeMessage.getTradeId(), peerOpenedDisputeMessage.getUid(), peerOpenedDisputeMessage.getTradeId(), peerOpenedDisputeMessage.getUid(),
chatMessage.getUid()); chatMessage.getUid());
clearPendingMessage();
// We use the chatMessage wrapped inside the peerOpenedDisputeMessage for // We use the chatMessage wrapped inside the peerOpenedDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg // the state, as that is displayed to the user and we only persist that msg
chatMessage.setStoredInMailbox(true); chatMessage.setStoredInMailbox(true);
@ -690,6 +699,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
peerOpenedDisputeMessage.getTradeId(), peerOpenedDisputeMessage.getUid(), peerOpenedDisputeMessage.getTradeId(), peerOpenedDisputeMessage.getUid(),
chatMessage.getUid(), errorMessage); chatMessage.getUid(), errorMessage);
clearPendingMessage();
// We use the chatMessage wrapped inside the peerOpenedDisputeMessage for // We use the chatMessage wrapped inside the peerOpenedDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg // the state, as that is displayed to the user and we only persist that msg
chatMessage.setSendMessageError(errorMessage); chatMessage.setSendMessageError(errorMessage);
@ -732,6 +742,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
log.info("Send {} to peer {}. tradeId={}, disputeResultMessage.uid={}, chatMessage.uid={}", log.info("Send {} to peer {}. tradeId={}, disputeResultMessage.uid={}, chatMessage.uid={}",
disputeResultMessage.getClass().getSimpleName(), peersNodeAddress, disputeResultMessage.getTradeId(), disputeResultMessage.getClass().getSimpleName(), peersNodeAddress, disputeResultMessage.getTradeId(),
disputeResultMessage.getUid(), chatMessage.getUid()); disputeResultMessage.getUid(), chatMessage.getUid());
recordPendingMessage(disputeResultMessage.getClass().getSimpleName());
mailboxMessageService.sendEncryptedMailboxMessage(peersNodeAddress, mailboxMessageService.sendEncryptedMailboxMessage(peersNodeAddress,
dispute.getTraderPubKeyRing(), dispute.getTraderPubKeyRing(),
disputeResultMessage, disputeResultMessage,
@ -744,6 +755,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
disputeResultMessage.getTradeId(), disputeResultMessage.getUid(), disputeResultMessage.getTradeId(), disputeResultMessage.getUid(),
chatMessage.getUid()); chatMessage.getUid());
clearPendingMessage();
// We use the chatMessage wrapped inside the disputeResultMessage for // We use the chatMessage wrapped inside the disputeResultMessage for
// the state, as that is displayed to the user and we only persist that msg // the state, as that is displayed to the user and we only persist that msg
chatMessage.setArrived(true); chatMessage.setArrived(true);
@ -758,6 +770,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
disputeResultMessage.getTradeId(), disputeResultMessage.getUid(), disputeResultMessage.getTradeId(), disputeResultMessage.getUid(),
chatMessage.getUid()); chatMessage.getUid());
clearPendingMessage();
// We use the chatMessage wrapped inside the disputeResultMessage for // We use the chatMessage wrapped inside the disputeResultMessage for
// the state, as that is displayed to the user and we only persist that msg // the state, as that is displayed to the user and we only persist that msg
chatMessage.setStoredInMailbox(true); chatMessage.setStoredInMailbox(true);
@ -772,6 +785,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
disputeResultMessage.getTradeId(), disputeResultMessage.getUid(), disputeResultMessage.getTradeId(), disputeResultMessage.getUid(),
chatMessage.getUid(), errorMessage); chatMessage.getUid(), errorMessage);
clearPendingMessage();
// We use the chatMessage wrapped inside the disputeResultMessage for // We use the chatMessage wrapped inside the disputeResultMessage for
// the state, as that is displayed to the user and we only persist that msg // the state, as that is displayed to the user and we only persist that msg
chatMessage.setSendMessageError(errorMessage); chatMessage.setSendMessageError(errorMessage);
@ -991,4 +1005,19 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
return null; return null;
} }
} }
public boolean hasPendingMessageAtShutdown() {
if (pendingOutgoingMessage.length() > 0) {
log.warn("{} has an outgoing message pending: {}", this.getClass().getSimpleName(), pendingOutgoingMessage);
return true;
}
return false;
}
private void recordPendingMessage(String className) {
pendingOutgoingMessage = className;
}
private void clearPendingMessage() {
pendingOutgoingMessage = "";
}
} }

View File

@ -3127,6 +3127,9 @@ popup.info.shutDownWithOpenOffers=Bisq is being shut down, but there are open of
(i.e., make sure it doesn't go into standby mode...monitor standby is not a problem). (i.e., make sure it doesn't go into standby mode...monitor standby is not a problem).
popup.info.shutDownWithTradeInit={0}\n\ popup.info.shutDownWithTradeInit={0}\n\
This trade has not finished initializing; shutting down now will probably make it corrupted. Please wait a minute and try again. This trade has not finished initializing; shutting down now will probably make it corrupted. Please wait a minute and try again.
popup.info.shutDownWithDisputeInit=Bisq is being shut down, but there is a Dispute system message still pending.\n\
Please wait a minute before shutting down.\n\
For further help please contact the Bisq support channel at the Bisq Matrix Space.
popup.info.qubesOSSetupInfo=It appears you are running Bisq on Qubes OS. \n\n\ 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]. Please make sure your Bisq qube is setup according to our Setup Guide at [HYPERLINK:https://bisq.wiki/Running_Bisq_on_Qubes].
popup.info.p2pStatusIndicator.red={0}\n\n\ popup.info.p2pStatusIndicator.red={0}\n\n\

View File

@ -40,6 +40,8 @@ import bisq.core.dao.governance.voteresult.MissingDataRequestService;
import bisq.core.locale.Res; import bisq.core.locale.Res;
import bisq.core.offer.OpenOffer; import bisq.core.offer.OpenOffer;
import bisq.core.offer.OpenOfferManager; import bisq.core.offer.OpenOfferManager;
import bisq.core.support.dispute.mediation.MediationManager;
import bisq.core.support.dispute.refund.RefundManager;
import bisq.core.trade.TradeManager; import bisq.core.trade.TradeManager;
import bisq.core.trade.model.bisq_v1.Trade; import bisq.core.trade.model.bisq_v1.Trade;
import bisq.core.user.Cookie; import bisq.core.user.Cookie;
@ -369,7 +371,11 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
if (shutdownStage1) { if (shutdownStage1) {
shutDownByUserCheckOffers().thenAccept(shutdownStage2 -> { shutDownByUserCheckOffers().thenAccept(shutdownStage2 -> {
if (shutdownStage2) { if (shutdownStage2) {
stop(); shutDownByUserCheckDisputes().thenAccept(shutdownStage3 -> {
if (shutdownStage3) {
stop();
}
});
} }
}); });
} }
@ -377,6 +383,7 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
} }
private CompletableFuture<Boolean> shutDownByUserCheckTrades() { private CompletableFuture<Boolean> shutDownByUserCheckTrades() {
log.info("Checking trades at shutdown");
final CompletableFuture<Boolean> asyncStatus = new CompletableFuture<>(); final CompletableFuture<Boolean> asyncStatus = new CompletableFuture<>();
Instant fiveMinutesAgo = Instant.ofEpochSecond(Instant.now().getEpochSecond() - TimeUnit.MINUTES.toSeconds(5)); Instant fiveMinutesAgo = Instant.ofEpochSecond(Instant.now().getEpochSecond() - TimeUnit.MINUTES.toSeconds(5));
String tradeIdsWithOperationsPending = ""; String tradeIdsWithOperationsPending = "";
@ -404,6 +411,7 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
} }
private CompletableFuture<Boolean> shutDownByUserCheckOffers() { private CompletableFuture<Boolean> shutDownByUserCheckOffers() {
log.info("Checking offers at shutdown");
final CompletableFuture<Boolean> asyncStatus = new CompletableFuture<>(); final CompletableFuture<Boolean> asyncStatus = new CompletableFuture<>();
boolean hasOpenOffers = false; boolean hasOpenOffers = false;
for (OpenOffer openOffer : injector.getInstance(OpenOfferManager.class).getObservableList()) { for (OpenOffer openOffer : injector.getInstance(OpenOfferManager.class).getObservableList()) {
@ -434,6 +442,24 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
return asyncStatus; return asyncStatus;
} }
private CompletableFuture<Boolean> shutDownByUserCheckDisputes() {
log.info("Checking disputes at shutdown");
final CompletableFuture<Boolean> asyncStatus = new CompletableFuture<>();
if (injector.getInstance(MediationManager.class).hasPendingMessageAtShutdown() ||
injector.getInstance(RefundManager.class).hasPendingMessageAtShutdown()) {
// We show a popup to inform user that some messages are still being sent.
new Popup().warning(Res.get("popup.info.shutDownWithDisputeInit"))
.actionButtonText(Res.get("shared.okWait"))
.onAction(() -> asyncStatus.complete(false))
.closeButtonText(Res.get("shared.closeAnywayDanger"))
.onClose(() -> asyncStatus.complete(true))
.show();
} else {
asyncStatus.complete(true);
}
return asyncStatus;
}
// Used for debugging trade process // Used for debugging trade process
private void showDebugWindow(Scene scene, Injector injector) { private void showDebugWindow(Scene scene, Injector injector) {
ViewLoader viewLoader = injector.getInstance(ViewLoader.class); ViewLoader viewLoader = injector.getInstance(ViewLoader.class);