diff --git a/src/main/java/io/bitsquare/trade/TradeManager.java b/src/main/java/io/bitsquare/trade/TradeManager.java index 4521d080ec..1d9d7d7dc4 100644 --- a/src/main/java/io/bitsquare/trade/TradeManager.java +++ b/src/main/java/io/bitsquare/trade/TradeManager.java @@ -84,7 +84,6 @@ public class TradeManager { //TODO store TakerAsSellerProtocol in trade private final Map takerAsSellerProtocolMap = new HashMap<>(); private final Map offererAsBuyerProtocolMap = new HashMap<>(); - private final Map createOfferCoordinatorMap = new HashMap<>(); private final ObservableMap offers = FXCollections.observableHashMap(); private final ObservableMap pendingTrades = FXCollections.observableHashMap(); @@ -167,36 +166,23 @@ public class TradeManager { settings.getAcceptedCountries(), settings.getAcceptedLanguageLocales()); - if (createOfferCoordinatorMap.containsKey(offer.getId())) { - errorMessageHandler.handleErrorMessage("A createOfferCoordinator for the offer with the id " + offer - .getId() + " " + - "already exists."); - } - else { - CreateOfferCoordinator createOfferCoordinator = new CreateOfferCoordinator(persistence, - offer, - walletFacade, - (transactionId) -> { - try { - offer.setOfferFeePaymentTxID(transactionId.getHashAsString()); - addOffer(offer); - createOfferCoordinatorMap.remove(offer.getId()); + CreateOfferCoordinator createOfferCoordinator = new CreateOfferCoordinator( + offer, + walletFacade, + (transactionId) -> { + try { + offer.setOfferFeePaymentTxID(transactionId.getHashAsString()); + addOffer(offer); + resultHandler.onResult(transactionId); + } catch (Exception e) { + errorMessageHandler.handleErrorMessage("Could not save offer. Reason: " + + (e.getCause() != null ? e.getCause().getMessage() : e.toString())); + } + }, + (message, throwable) -> errorMessageHandler.handleErrorMessage(message), + offerRepository); - resultHandler.onResult(transactionId); - } catch (Exception e) { - //TODO retry policy - errorMessageHandler.handleErrorMessage("Could not save offer. Reason: " + - (e.getCause() != null ? e.getCause().getMessage() : e.toString())); - createOfferCoordinatorMap.remove(offer.getId()); - } - }, - (message, throwable) -> { - errorMessageHandler.handleErrorMessage(message); - createOfferCoordinatorMap.remove(offer.getId()); - }, offerRepository); - createOfferCoordinatorMap.put(offer.getId(), createOfferCoordinator); - createOfferCoordinator.start(); - } + createOfferCoordinator.start(); } private void addOffer(Offer offer) { diff --git a/src/main/java/io/bitsquare/trade/protocol/createoffer/CreateOfferCoordinator.java b/src/main/java/io/bitsquare/trade/protocol/createoffer/CreateOfferCoordinator.java index 722b900e84..c9bd515b22 100644 --- a/src/main/java/io/bitsquare/trade/protocol/createoffer/CreateOfferCoordinator.java +++ b/src/main/java/io/bitsquare/trade/protocol/createoffer/CreateOfferCoordinator.java @@ -20,7 +20,6 @@ package io.bitsquare.trade.protocol.createoffer; import io.bitsquare.btc.WalletFacade; import io.bitsquare.offer.Offer; import io.bitsquare.offer.OfferRepository; -import io.bitsquare.persistence.Persistence; import io.bitsquare.trade.handlers.TransactionResultHandler; import io.bitsquare.util.task.FaultHandler; @@ -29,57 +28,13 @@ import org.bitcoinj.core.Transaction; import com.google.common.util.concurrent.FutureCallback; -import java.io.Serializable; - -import javax.annotation.concurrent.Immutable; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Responsible for coordinating tasks involved in the create offer process. - * It holds the model.state of the current process and support recovery if possible. */ -//TODO recover policy, timer - -@Immutable public class CreateOfferCoordinator { - public enum State { - INITED, - STARTED, - VALIDATED, - OFFER_FEE_TX_CREATED, - OFFER_FEE_BROAD_CASTED, - OFFER_PUBLISHED_TO_DHT - } - - /** - * The model is not immutable but only exposed to the CreateOfferCoordinator - */ - static class Model implements Serializable { - private static final long serialVersionUID = 3027720554200858916L; - - private final Persistence persistence; - private State state; - //TODO use tx id - Transaction transaction; - - Model(Persistence persistence) { - this.persistence = persistence; - } - - public State getState() { - return state; - } - - public void setState(State state) { - this.state = state; - - //TODO will have performance issues, but could be handled inside the persistence solution (queue up save - // requests and exec. them on dedicated thread) - persistence.write(this, "state", state); - } - } private static final Logger log = LoggerFactory.getLogger(CreateOfferCoordinator.class); @@ -87,43 +42,30 @@ public class CreateOfferCoordinator { private final WalletFacade walletFacade; private final TransactionResultHandler resultHandler; private final FaultHandler faultHandler; - private final Model model; private final OfferRepository offerRepository; - public CreateOfferCoordinator(Persistence persistence, Offer offer, WalletFacade walletFacade, - TransactionResultHandler resultHandler, FaultHandler faultHandler, - OfferRepository offerRepository) { - this(offer, walletFacade, resultHandler, faultHandler, new Model(persistence), offerRepository); - } - - // for recovery from model public CreateOfferCoordinator(Offer offer, WalletFacade walletFacade, TransactionResultHandler resultHandler, - FaultHandler faultHandler, Model model, OfferRepository offerRepository) { + FaultHandler faultHandler, OfferRepository offerRepository) { this.offer = offer; this.walletFacade = walletFacade; this.resultHandler = resultHandler; this.faultHandler = faultHandler; - this.model = model; this.offerRepository = offerRepository; - - model.setState(State.INITED); } public void start() { - model.setState(State.STARTED); - try { offer.validate(); - model.setState(State.VALIDATED); } catch (Exception ex) { faultHandler.handleFault("Offer validation failed", ex); return; } + Transaction transaction; + try { - model.transaction = walletFacade.createOfferFeeTx(offer.getId()); - model.setState(State.OFFER_FEE_TX_CREATED); - offer.setOfferFeePaymentTxID(model.transaction.getHashAsString()); + transaction = walletFacade.createOfferFeeTx(offer.getId()); + offer.setOfferFeePaymentTxID(transaction.getHashAsString()); } catch (InsufficientMoneyException ex) { faultHandler.handleFault( "Offer fee payment failed because there is insufficient money in the trade wallet", ex); @@ -134,7 +76,7 @@ public class CreateOfferCoordinator { } try { - walletFacade.broadcastCreateOfferFeeTx(model.transaction, new FutureCallback() { + walletFacade.broadcastCreateOfferFeeTx(transaction, new FutureCallback() { @Override public void onSuccess(Transaction transaction) { log.info("sendResult onSuccess:" + transaction); @@ -145,8 +87,7 @@ public class CreateOfferCoordinator { } try { - model.setState(State.OFFER_FEE_BROAD_CASTED); - offerRepository.addOffer(offer, CreateOfferCoordinator.this::addOfferResultHandler, faultHandler); + offerRepository.addOffer(offer, () -> resultHandler.onResult(transaction), faultHandler); } catch (Exception e) { faultHandler.handleFault("Offer fee payment failed.", e); } @@ -162,39 +103,4 @@ public class CreateOfferCoordinator { return; } } - - private void addOfferResultHandler() { - model.setState(State.OFFER_PUBLISHED_TO_DHT); - resultHandler.onResult(model.transaction); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Recovery - /////////////////////////////////////////////////////////////////////////////////////////// - - public void recover() { - switch (model.getState()) { - case INITED: - case STARTED: - case VALIDATED: - case OFFER_FEE_TX_CREATED: - // we start over again, no critical and expensive work done yet - start(); - break; - case OFFER_FEE_BROAD_CASTED: - // actually the only replay case here, tx publish was successful but storage to dht failed. - // Republish the offer to DHT - offerRepository.addOffer(offer, this::addOfferResultHandler, faultHandler); - break; - case OFFER_PUBLISHED_TO_DHT: - // should be impossible - log.warn("That case must not happen."); - break; - default: - log.error("Illegal state passes. That must not happen"); - break; - } - } - }