confirm payment sent and received off main thread

This commit is contained in:
woodser 2022-07-30 16:07:29 -04:00
parent 50126874a0
commit 3d43ae1f20
4 changed files with 90 additions and 82 deletions

View file

@ -126,32 +126,34 @@ public abstract class BuyerProtocol extends DisputeProtocol {
public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
System.out.println("BuyerProtocol.onPaymentStarted()");
synchronized (trade) {
latchTrade();
this.errorMessageHandler = errorMessageHandler;
BuyerEvent event = BuyerEvent.PAYMENT_SENT;
expect(phase(Trade.Phase.DEPOSIT_UNLOCKED)
.with(event)
.preCondition(trade.confirmPermitted()))
.setup(tasks(ApplyFilter.class,
getVerifyPeersFeePaymentClass(),
//UpdateMultisigWithTradingPeer.class, // TODO (woodser): can use this to test protocol with updated multisig from peer. peer should attempt to send updated multisig hex earlier as part of protocol. cannot use with countdown latch because response comes back in a separate thread and blocks on trade
BuyerPreparesPaymentSentMessage.class,
//BuyerSetupPayoutTxListener.class,
BuyerSendsPaymentSentMessage.class) // don't latch trade because this blocks and runs in background
.using(new TradeTaskRunner(trade,
() -> {
this.errorMessageHandler = null;
handleTaskRunnerSuccess(event);
resultHandler.handleResult();
},
(errorMessage) -> {
handleTaskRunnerFault(event, errorMessage);
})))
.run(() -> trade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_PAYMENT_SENT))
.executeTasks();
awaitTradeLatch();
}
new Thread(() -> {
synchronized (trade) {
latchTrade();
this.errorMessageHandler = errorMessageHandler;
BuyerEvent event = BuyerEvent.PAYMENT_SENT;
expect(phase(Trade.Phase.DEPOSIT_UNLOCKED)
.with(event)
.preCondition(trade.confirmPermitted()))
.setup(tasks(ApplyFilter.class,
getVerifyPeersFeePaymentClass(),
//UpdateMultisigWithTradingPeer.class, // TODO (woodser): can use this to test protocol with updated multisig from peer. peer should attempt to send updated multisig hex earlier as part of protocol. cannot use with countdown latch because response comes back in a separate thread and blocks on trade
BuyerPreparesPaymentSentMessage.class,
//BuyerSetupPayoutTxListener.class,
BuyerSendsPaymentSentMessage.class) // don't latch trade because this blocks and runs in background
.using(new TradeTaskRunner(trade,
() -> {
this.errorMessageHandler = null;
handleTaskRunnerSuccess(event);
resultHandler.handleResult();
},
(errorMessage) -> {
handleTaskRunnerFault(event, errorMessage);
})))
.run(() -> trade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_PAYMENT_SENT))
.executeTasks(true);
awaitTradeLatch();
}
}).start();
}
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -124,29 +124,31 @@ public abstract class SellerProtocol extends DisputeProtocol {
public void onPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
log.info("SellerProtocol.onPaymentReceived()");
synchronized (trade) {
latchTrade();
this.errorMessageHandler = errorMessageHandler;
SellerEvent event = SellerEvent.PAYMENT_RECEIVED;
expect(anyPhase(Trade.Phase.PAYMENT_SENT, Trade.Phase.PAYMENT_RECEIVED)
.with(event)
.preCondition(trade.confirmPermitted()))
.setup(tasks(
ApplyFilter.class,
getVerifyPeersFeePaymentClass(),
SellerPreparesPaymentReceivedMessage.class,
SellerSendsPaymentReceivedMessage.class)
.using(new TradeTaskRunner(trade, () -> {
this.errorMessageHandler = null;
handleTaskRunnerSuccess(event);
resultHandler.handleResult();
}, (errorMessage) -> {
handleTaskRunnerFault(event, errorMessage);
})))
.run(() -> trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_PAYMENT_RECEIPT))
.executeTasks();
awaitTradeLatch();
}
new Thread(() -> {
synchronized (trade) {
latchTrade();
this.errorMessageHandler = errorMessageHandler;
SellerEvent event = SellerEvent.PAYMENT_RECEIVED;
expect(anyPhase(Trade.Phase.PAYMENT_SENT, Trade.Phase.PAYMENT_RECEIVED)
.with(event)
.preCondition(trade.confirmPermitted()))
.setup(tasks(
ApplyFilter.class,
getVerifyPeersFeePaymentClass(),
SellerPreparesPaymentReceivedMessage.class,
SellerSendsPaymentReceivedMessage.class)
.using(new TradeTaskRunner(trade, () -> {
this.errorMessageHandler = null;
handleTaskRunnerSuccess(event);
resultHandler.handleResult();
}, (errorMessage) -> {
handleTaskRunnerFault(event, errorMessage);
})))
.run(() -> trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_PAYMENT_RECEIPT))
.executeTasks(true);
awaitTradeLatch();
}
}).start();
}
@Override

View file

@ -159,41 +159,42 @@ public class BuyerStep2View extends TradeStepView {
showPopup();
} else if (state.ordinal() <= Trade.State.BUYER_SEND_FAILED_PAYMENT_SENT_MSG.ordinal()) {
if (!trade.hasFailed()) {
UserThread.execute(() -> {
switch (state) {
case BUYER_CONFIRMED_IN_UI_PAYMENT_SENT:
case BUYER_SENT_PAYMENT_SENT_MSG:
busyAnimation.play();
statusLabel.setText(Res.get("shared.sendingConfirmation"));
model.setMessageStateProperty(MessageState.SENT);
timeoutTimer = UserThread.runAfter(() -> {
busyAnimation.stop();
statusLabel.setText(Res.get("shared.sendingConfirmationAgain"));
}, 10);
break;
case BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG:
busyAnimation.stop();
statusLabel.setText(Res.get("shared.messageArrived"));
model.setMessageStateProperty(MessageState.ARRIVED);
break;
case BUYER_STORED_IN_MAILBOX_PAYMENT_SENT_MSG:
busyAnimation.stop();
statusLabel.setText(Res.get("shared.messageStoredInMailbox"));
model.setMessageStateProperty(MessageState.STORED_IN_MAILBOX);
break;
case BUYER_SEND_FAILED_PAYMENT_SENT_MSG:
// We get a popup and the trade closed, so we dont need to show anything here
busyAnimation.stop();
statusLabel.setText("");
model.setMessageStateProperty(MessageState.FAILED);
break;
default:
log.warn("Unexpected case: State={}, tradeId={} " + state.name(), trade.getId());
switch (state) {
case BUYER_CONFIRMED_IN_UI_PAYMENT_SENT:
busyAnimation.play();
statusLabel.setText("Confirming payment sent...");
break;
case BUYER_SENT_PAYMENT_SENT_MSG:
busyAnimation.play();
statusLabel.setText(Res.get("shared.sendingConfirmation"));
model.setMessageStateProperty(MessageState.SENT);
timeoutTimer = UserThread.runAfter(() -> {
busyAnimation.stop();
statusLabel.setText(Res.get("shared.sendingConfirmationAgain"));
break;
}
});
}, 10);
break;
case BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG:
busyAnimation.stop();
statusLabel.setText(Res.get("shared.messageArrived"));
model.setMessageStateProperty(MessageState.ARRIVED);
break;
case BUYER_STORED_IN_MAILBOX_PAYMENT_SENT_MSG:
busyAnimation.stop();
statusLabel.setText(Res.get("shared.messageStoredInMailbox"));
model.setMessageStateProperty(MessageState.STORED_IN_MAILBOX);
break;
case BUYER_SEND_FAILED_PAYMENT_SENT_MSG:
// We get a popup and the trade closed, so we dont need to show anything here
busyAnimation.stop();
statusLabel.setText("");
model.setMessageStateProperty(MessageState.FAILED);
break;
default:
log.warn("Unexpected case: State={}, tradeId={} " + state.name(), trade.getId());
busyAnimation.stop();
statusLabel.setText(Res.get("shared.sendingConfirmationAgain"));
break;
}
} else {
log.warn("Trade contains error message {}", trade.getErrorMessage());
statusLabel.setText("");

View file

@ -120,6 +120,9 @@ public class SellerStep3View extends TradeStepView {
if (!trade.hasFailed()) {
switch (state) {
case SELLER_CONFIRMED_IN_UI_PAYMENT_RECEIPT:
busyAnimation.play();
statusLabel.setText(Res.get("Confirming payment received..."));
break;
case SELLER_PUBLISHED_PAYOUT_TX:
case SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG:
case SELLER_SENT_PAYMENT_RECEIVED_MSG: