mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-06-24 23:00:36 -04:00
improve error handling when clones taken at the same time
This commit is contained in:
parent
c7a3a9740f
commit
cf9a37f295
4 changed files with 46 additions and 24 deletions
|
@ -145,6 +145,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
|
||||||
private static final long DELETE_AFTER_MS = TradeProtocol.TRADE_STEP_TIMEOUT_SECONDS;
|
private static final long DELETE_AFTER_MS = TradeProtocol.TRADE_STEP_TIMEOUT_SECONDS;
|
||||||
private static final int NUM_CONFIRMATIONS_FOR_SCHEDULED_IMPORT = 5;
|
private static final int NUM_CONFIRMATIONS_FOR_SCHEDULED_IMPORT = 5;
|
||||||
protected final Object pollLock = new Object();
|
protected final Object pollLock = new Object();
|
||||||
|
private final Object removeTradeOnErrorLock = new Object();
|
||||||
protected static final Object importMultisigLock = new Object();
|
protected static final Object importMultisigLock = new Object();
|
||||||
private boolean pollInProgress;
|
private boolean pollInProgress;
|
||||||
private boolean restartInProgress;
|
private boolean restartInProgress;
|
||||||
|
@ -1608,11 +1609,12 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
|
||||||
}
|
}
|
||||||
|
|
||||||
// shut down trade threads
|
// shut down trade threads
|
||||||
isInitialized = false;
|
|
||||||
isShutDown = true;
|
isShutDown = true;
|
||||||
List<Runnable> shutDownThreads = new ArrayList<>();
|
List<Runnable> shutDownThreads = new ArrayList<>();
|
||||||
shutDownThreads.add(() -> ThreadUtils.shutDown(getId()));
|
shutDownThreads.add(() -> ThreadUtils.shutDown(getId()));
|
||||||
ThreadUtils.awaitTasks(shutDownThreads);
|
ThreadUtils.awaitTasks(shutDownThreads);
|
||||||
|
stopProtocolTimeout();
|
||||||
|
isInitialized = false;
|
||||||
|
|
||||||
// save and close
|
// save and close
|
||||||
if (wallet != null) {
|
if (wallet != null) {
|
||||||
|
@ -1765,25 +1767,31 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeTradeOnError() {
|
private void removeTradeOnError() {
|
||||||
|
synchronized (removeTradeOnErrorLock) {
|
||||||
|
|
||||||
|
// skip if already shut down or removed
|
||||||
|
if (isShutDown || !processModel.getTradeManager().hasTrade(getId())) return;
|
||||||
log.warn("removeTradeOnError() trade={}, tradeId={}, state={}", getClass().getSimpleName(), getShortId(), getState());
|
log.warn("removeTradeOnError() trade={}, tradeId={}, state={}", getClass().getSimpleName(), getShortId(), getState());
|
||||||
|
|
||||||
// force close and re-open wallet in case stuck
|
// force close and re-open wallet in case stuck
|
||||||
forceCloseWallet();
|
forceCloseWallet();
|
||||||
if (isDepositRequested()) getWallet();
|
if (isDepositRequested()) getWallet();
|
||||||
|
|
||||||
|
// clear and shut down trade
|
||||||
|
onShutDownStarted();
|
||||||
|
clearAndShutDown();
|
||||||
|
|
||||||
// shut down trade thread
|
// shut down trade thread
|
||||||
try {
|
try {
|
||||||
ThreadUtils.shutDown(getId(), 1000l);
|
ThreadUtils.shutDown(getId(), 5000l);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("Error shutting down trade thread for {} {}: {}", getClass().getSimpleName(), getId(), e.getMessage());
|
log.warn("Error shutting down trade thread for {} {}: {}", getClass().getSimpleName(), getId(), e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear and shut down trade
|
|
||||||
clearAndShutDown();
|
|
||||||
|
|
||||||
// unregister trade
|
// unregister trade
|
||||||
processModel.getTradeManager().unregisterTrade(this);
|
processModel.getTradeManager().unregisterTrade(this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Model implementation
|
// Model implementation
|
||||||
|
@ -1824,6 +1832,13 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
|
||||||
getProtocol().startTimeout(TradeProtocol.TRADE_STEP_TIMEOUT_SECONDS);
|
getProtocol().startTimeout(TradeProtocol.TRADE_STEP_TIMEOUT_SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stopProtocolTimeout() {
|
||||||
|
if (!isInitialized) return;
|
||||||
|
TradeProtocol protocol = getProtocol();
|
||||||
|
if (protocol == null) return;
|
||||||
|
protocol.stopTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
public void setState(State state) {
|
public void setState(State state) {
|
||||||
if (isInitialized) {
|
if (isInitialized) {
|
||||||
// We don't want to log at startup the setState calls from all persisted trades
|
// We don't want to log at startup the setState calls from all persisted trades
|
||||||
|
|
|
@ -563,9 +563,14 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||||
Optional<OpenOffer> openOfferOptional = openOfferManager.getOpenOffer(request.getOfferId());
|
Optional<OpenOffer> openOfferOptional = openOfferManager.getOpenOffer(request.getOfferId());
|
||||||
if (!openOfferOptional.isPresent()) return;
|
if (!openOfferOptional.isPresent()) return;
|
||||||
OpenOffer openOffer = openOfferOptional.get();
|
OpenOffer openOffer = openOfferOptional.get();
|
||||||
if (openOffer.getState() != OpenOffer.State.AVAILABLE) return;
|
|
||||||
Offer offer = openOffer.getOffer();
|
Offer offer = openOffer.getOffer();
|
||||||
|
|
||||||
|
// check availability
|
||||||
|
if (openOffer.getState() != OpenOffer.State.AVAILABLE) {
|
||||||
|
log.warn("Ignoring InitTradeRequest to maker because offer is not available, offerId={}, sender={}", request.getOfferId(), sender);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// validate challenge
|
// validate challenge
|
||||||
if (openOffer.getChallenge() != null && !HavenoUtils.getChallengeHash(openOffer.getChallenge()).equals(HavenoUtils.getChallengeHash(request.getChallenge()))) {
|
if (openOffer.getChallenge() != null && !HavenoUtils.getChallengeHash(openOffer.getChallenge()).equals(HavenoUtils.getChallengeHash(request.getChallenge()))) {
|
||||||
log.warn("Ignoring InitTradeRequest to maker because challenge is incorrect, tradeId={}, sender={}", request.getOfferId(), sender);
|
log.warn("Ignoring InitTradeRequest to maker because challenge is incorrect, tradeId={}, sender={}", request.getOfferId(), sender);
|
||||||
|
@ -980,9 +985,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||||
closedTradableManager.add(trade);
|
closedTradableManager.add(trade);
|
||||||
trade.setCompleted(true);
|
trade.setCompleted(true);
|
||||||
removeTrade(trade, true);
|
removeTrade(trade, true);
|
||||||
|
xmrWalletService.swapPayoutAddressEntryToAvailable(trade.getId()); // TODO The address entry should have been removed already. Check and if its the case remove that.
|
||||||
// TODO The address entry should have been removed already. Check and if its the case remove that.
|
|
||||||
xmrWalletService.swapPayoutAddressEntryToAvailable(trade.getId());
|
|
||||||
requestPersistence();
|
requestPersistence();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -990,6 +993,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||||
log.warn("Unregistering {} {}", trade.getClass().getSimpleName(), trade.getId());
|
log.warn("Unregistering {} {}", trade.getClass().getSimpleName(), trade.getId());
|
||||||
removeTrade(trade, true);
|
removeTrade(trade, true);
|
||||||
removeFailedTrade(trade);
|
removeFailedTrade(trade);
|
||||||
|
xmrWalletService.swapPayoutAddressEntryToAvailable(trade.getId()); // TODO The address entry should have been removed already. Check and if its the case remove that.
|
||||||
requestPersistence();
|
requestPersistence();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1274,11 +1278,15 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||||
return offer.getDirection() == OfferDirection.SELL;
|
return offer.getDirection() == OfferDirection.SELL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO (woodser): make Optional<Trade> versus Trade return types consistent
|
// TODO: make Optional<Trade> versus Trade return types consistent
|
||||||
public Trade getTrade(String tradeId) {
|
public Trade getTrade(String tradeId) {
|
||||||
return getOpenTrade(tradeId).orElseGet(() -> getClosedTrade(tradeId).orElseGet(() -> getFailedTrade(tradeId).orElseGet(() -> null)));
|
return getOpenTrade(tradeId).orElseGet(() -> getClosedTrade(tradeId).orElseGet(() -> getFailedTrade(tradeId).orElseGet(() -> null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasTrade(String tradeId) {
|
||||||
|
return getTrade(tradeId) != null;
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<Trade> getOpenTrade(String tradeId) {
|
public Optional<Trade> getOpenTrade(String tradeId) {
|
||||||
synchronized (tradableList.getList()) {
|
synchronized (tradableList.getList()) {
|
||||||
return tradableList.stream().filter(e -> e.getId().equals(tradeId)).findFirst();
|
return tradableList.stream().filter(e -> e.getId().equals(tradeId)).findFirst();
|
||||||
|
|
|
@ -842,7 +842,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void stopTimeout() {
|
public synchronized void stopTimeout() {
|
||||||
synchronized (timeoutTimerLock) {
|
synchronized (timeoutTimerLock) {
|
||||||
if (timeoutTimer != null) {
|
if (timeoutTimer != null) {
|
||||||
timeoutTimer.stop();
|
timeoutTimer.stop();
|
||||||
|
|
|
@ -346,8 +346,7 @@ public class DepositView extends ActivatableView<VBox, Void> {
|
||||||
List<XmrAddressEntry> addressEntries = xmrWalletService.getAddressEntries();
|
List<XmrAddressEntry> addressEntries = xmrWalletService.getAddressEntries();
|
||||||
List<DepositListItem> items = new ArrayList<>();
|
List<DepositListItem> items = new ArrayList<>();
|
||||||
for (XmrAddressEntry addressEntry : addressEntries) {
|
for (XmrAddressEntry addressEntry : addressEntries) {
|
||||||
DepositListItem item = new DepositListItem(addressEntry, xmrWalletService, formatter);
|
if (addressEntry.isTradePayout()) continue; // do not show trade payout addresses
|
||||||
if (addressEntry.isTradePayout() && BigInteger.ZERO.equals(item.getBalanceAsBI())) continue; // do not show empty trade payout addresses
|
|
||||||
items.add(new DepositListItem(addressEntry, xmrWalletService, formatter));
|
items.add(new DepositListItem(addressEntry, xmrWalletService, formatter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue