mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-11-17 00:07:49 +00:00
resend payment sent msg until ack, payment received msg if not published
improve payment confirmation states in ui
This commit is contained in:
parent
aea831bafd
commit
7e8e145c85
4 changed files with 83 additions and 44 deletions
|
@ -53,9 +53,9 @@ public class BuyerProtocol extends DisputeProtocol {
|
||||||
protected void onInitialized() {
|
protected void onInitialized() {
|
||||||
super.onInitialized();
|
super.onInitialized();
|
||||||
|
|
||||||
// re-send payment sent message if not arrived
|
// re-send payment sent message if not acked
|
||||||
synchronized (trade) {
|
synchronized (trade) {
|
||||||
if (trade.getState().ordinal() >= Trade.State.BUYER_SENT_PAYMENT_SENT_MSG.ordinal() && trade.getState().ordinal() <= Trade.State.BUYER_SEND_FAILED_PAYMENT_SENT_MSG.ordinal()) {
|
if (trade.getState().ordinal() >= Trade.State.BUYER_SENT_PAYMENT_SENT_MSG.ordinal() && trade.getState().ordinal() < Trade.State.SELLER_RECEIVED_PAYMENT_SENT_MSG.ordinal()) {
|
||||||
latchTrade();
|
latchTrade();
|
||||||
given(anyPhase(Trade.Phase.PAYMENT_SENT)
|
given(anyPhase(Trade.Phase.PAYMENT_SENT)
|
||||||
.with(BuyerEvent.STARTUP))
|
.with(BuyerEvent.STARTUP))
|
||||||
|
|
|
@ -49,9 +49,9 @@ public class SellerProtocol extends DisputeProtocol {
|
||||||
protected void onInitialized() {
|
protected void onInitialized() {
|
||||||
super.onInitialized();
|
super.onInitialized();
|
||||||
|
|
||||||
// re-send payment received message if not arrived
|
// re-send payment received message if payout not published
|
||||||
synchronized (trade) {
|
synchronized (trade) {
|
||||||
if (trade.getState().ordinal() >= Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG.ordinal() && trade.getState().ordinal() <= Trade.State.SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG.ordinal()) {
|
if (trade.getState().ordinal() >= Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG.ordinal() && !trade.isPayoutPublished()) {
|
||||||
latchTrade();
|
latchTrade();
|
||||||
given(anyPhase(Trade.Phase.PAYMENT_RECEIVED)
|
given(anyPhase(Trade.Phase.PAYMENT_RECEIVED)
|
||||||
.with(SellerEvent.STARTUP))
|
.with(SellerEvent.STARTUP))
|
||||||
|
|
|
@ -17,7 +17,10 @@
|
||||||
|
|
||||||
package haveno.core.trade.protocol.tasks;
|
package haveno.core.trade.protocol.tasks;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import haveno.common.Timer;
|
import haveno.common.Timer;
|
||||||
|
import haveno.common.UserThread;
|
||||||
import haveno.common.crypto.PubKeyRing;
|
import haveno.common.crypto.PubKeyRing;
|
||||||
import haveno.common.taskrunner.TaskRunner;
|
import haveno.common.taskrunner.TaskRunner;
|
||||||
import haveno.core.network.MessageState;
|
import haveno.core.network.MessageState;
|
||||||
|
@ -45,6 +48,9 @@ import lombok.extern.slf4j.Slf4j;
|
||||||
public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask {
|
public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask {
|
||||||
private ChangeListener<MessageState> listener;
|
private ChangeListener<MessageState> listener;
|
||||||
private Timer timer;
|
private Timer timer;
|
||||||
|
private static final int MAX_RESEND_ATTEMPTS = 10;
|
||||||
|
private int delayInMin = 10;
|
||||||
|
private int resendCounter = 0;
|
||||||
|
|
||||||
public BuyerSendPaymentSentMessage(TaskRunner<Trade> taskHandler, Trade trade) {
|
public BuyerSendPaymentSentMessage(TaskRunner<Trade> taskHandler, Trade trade) {
|
||||||
super(taskHandler, trade);
|
super(taskHandler, trade);
|
||||||
|
@ -61,8 +67,6 @@ public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask
|
||||||
super.run();
|
super.run();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
failed(t);
|
failed(t);
|
||||||
} finally {
|
|
||||||
cleanup();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,22 +109,21 @@ public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setStateSent() {
|
protected void setStateSent() {
|
||||||
if (trade.getState().ordinal() < Trade.State.BUYER_SENT_PAYMENT_SENT_MSG.ordinal()) {
|
if (trade.getState().ordinal() < Trade.State.BUYER_SENT_PAYMENT_SENT_MSG.ordinal()) trade.setStateIfValidTransitionTo(Trade.State.BUYER_SENT_PAYMENT_SENT_MSG);
|
||||||
trade.setStateIfValidTransitionTo(Trade.State.BUYER_SENT_PAYMENT_SENT_MSG);
|
tryToSendAgainLater();
|
||||||
}
|
|
||||||
processModel.getTradeManager().requestPersistence();
|
processModel.getTradeManager().requestPersistence();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setStateArrived() {
|
protected void setStateArrived() {
|
||||||
trade.setStateIfValidTransitionTo(Trade.State.BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG);
|
trade.setStateIfValidTransitionTo(Trade.State.BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG);
|
||||||
|
processModel.getTradeManager().requestPersistence();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setStateStoredInMailbox() {
|
protected void setStateStoredInMailbox() {
|
||||||
trade.setStateIfValidTransitionTo(Trade.State.BUYER_STORED_IN_MAILBOX_PAYMENT_SENT_MSG);
|
trade.setStateIfValidTransitionTo(Trade.State.BUYER_STORED_IN_MAILBOX_PAYMENT_SENT_MSG);
|
||||||
processModel.getTradeManager().requestPersistence();
|
processModel.getTradeManager().requestPersistence();
|
||||||
// TODO: schedule repeat sending like haveno?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -137,4 +140,40 @@ public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask
|
||||||
processModel.getPaymentSentMessageStateProperty().removeListener(listener);
|
processModel.getPaymentSentMessageStateProperty().removeListener(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void tryToSendAgainLater() {
|
||||||
|
|
||||||
|
// skip if already acked
|
||||||
|
if (trade.getState().ordinal() >= Trade.State.SELLER_RECEIVED_PAYMENT_SENT_MSG.ordinal()) return;
|
||||||
|
|
||||||
|
if (resendCounter >= MAX_RESEND_ATTEMPTS) {
|
||||||
|
cleanup();
|
||||||
|
log.warn("We never received an ACK message when sending the PaymentSentMessage to the peer. We stop trying to send the message.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("We will send the message again to the peer after a delay of {} min.", delayInMin);
|
||||||
|
if (timer != null) {
|
||||||
|
timer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
timer = UserThread.runAfter(this::run, delayInMin, TimeUnit.MINUTES);
|
||||||
|
|
||||||
|
if (resendCounter == 0) {
|
||||||
|
listener = (observable, oldValue, newValue) -> onMessageStateChange(newValue);
|
||||||
|
processModel.getPaymentSentMessageStateProperty().addListener(listener);
|
||||||
|
onMessageStateChange(processModel.getPaymentSentMessageStateProperty().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
delayInMin = delayInMin * 2;
|
||||||
|
resendCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onMessageStateChange(MessageState newValue) {
|
||||||
|
if (newValue == MessageState.ACKNOWLEDGED) {
|
||||||
|
trade.setStateIfValidTransitionTo(Trade.State.SELLER_RECEIVED_PAYMENT_SENT_MSG);
|
||||||
|
processModel.getTradeManager().requestPersistence();
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,43 +149,43 @@ public class BuyerStep2View extends TradeStepView {
|
||||||
|
|
||||||
if (trade.isDepositsUnlocked() && !trade.isPaymentSent()) {
|
if (trade.isDepositsUnlocked() && !trade.isPaymentSent()) {
|
||||||
showPopup();
|
showPopup();
|
||||||
} else if (state.ordinal() <= Trade.State.BUYER_SEND_FAILED_PAYMENT_SENT_MSG.ordinal()) {
|
} else if (state.ordinal() <= Trade.State.SELLER_RECEIVED_PAYMENT_SENT_MSG.ordinal()) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case BUYER_CONFIRMED_IN_UI_PAYMENT_SENT:
|
case BUYER_CONFIRMED_IN_UI_PAYMENT_SENT:
|
||||||
busyAnimation.play();
|
busyAnimation.play();
|
||||||
statusLabel.setText(Res.get("shared.preparingConfirmation"));
|
statusLabel.setText(Res.get("shared.preparingConfirmation"));
|
||||||
break;
|
break;
|
||||||
case BUYER_SENT_PAYMENT_SENT_MSG:
|
case BUYER_SENT_PAYMENT_SENT_MSG:
|
||||||
busyAnimation.play();
|
busyAnimation.play();
|
||||||
statusLabel.setText(Res.get("shared.sendingConfirmation"));
|
statusLabel.setText(Res.get("shared.sendingConfirmation"));
|
||||||
model.setMessageStateProperty(MessageState.SENT);
|
model.setMessageStateProperty(MessageState.SENT);
|
||||||
timeoutTimer = UserThread.runAfter(() -> {
|
timeoutTimer = UserThread.runAfter(() -> {
|
||||||
|
busyAnimation.stop();
|
||||||
|
statusLabel.setText(Res.get("shared.sendingConfirmationAgain"));
|
||||||
|
}, 10);
|
||||||
|
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 SELLER_RECEIVED_PAYMENT_SENT_MSG:
|
||||||
|
busyAnimation.stop();
|
||||||
|
statusLabel.setText(Res.get("shared.messageArrived"));
|
||||||
|
model.setMessageStateProperty(MessageState.ARRIVED);
|
||||||
|
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();
|
busyAnimation.stop();
|
||||||
statusLabel.setText(Res.get("shared.sendingConfirmationAgain"));
|
statusLabel.setText(Res.get("shared.sendingConfirmationAgain"));
|
||||||
}, 10);
|
break;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue