Refactor proposal domain and make it more thread safe

- Add MyProposalService and ProposalListService to split up responsibility and threading boundaries
- Make ProposalService running in parser thread. Refactor resonsibilities.
- Add thread context aware listeners
- Use injectable NodeExecutor to make parsre thread accessible for thread context aware listeners
- Add stream() method and Iterable<T> interface to PersistableList
- Add ProposalFactory to create proposals from its payload
- Add ProposalPayload and BlindVoteList to Tx
- Add getLastOutput method to Tx
This commit is contained in:
Manfred Karrer 2018-04-11 13:51:19 -05:00
parent a5a22b1edb
commit c07822da37
No known key found for this signature in database
GPG key ID: 401250966A6B2C46
6 changed files with 53 additions and 45 deletions

View file

@ -51,6 +51,7 @@ import bisq.core.dao.DaoSetup;
import bisq.core.dao.param.DaoParamService;
import bisq.core.dao.vote.blindvote.BlindVoteService;
import bisq.core.dao.vote.myvote.MyVoteService;
import bisq.core.dao.vote.proposal.MyProposalService;
import bisq.core.dao.vote.proposal.ProposalService;
import bisq.core.filter.FilterManager;
import bisq.core.locale.CurrencyUtil;
@ -231,6 +232,7 @@ public class BisqApp extends Application {
persistedDataHosts.add(injector.getInstance(FailedTradesManager.class));
persistedDataHosts.add(injector.getInstance(DisputeManager.class));
persistedDataHosts.add(injector.getInstance(P2PService.class));
persistedDataHosts.add(injector.getInstance(MyProposalService.class));
persistedDataHosts.add(injector.getInstance(ProposalService.class));
persistedDataHosts.add(injector.getInstance(BlindVoteService.class));
persistedDataHosts.add(injector.getInstance(MyVoteService.class));

View file

@ -27,18 +27,16 @@ import bisq.desktop.util.BSFormatter;
import bisq.desktop.util.BsqFormatter;
import bisq.core.btc.wallet.BsqWalletService;
import bisq.core.dao.blockchain.BsqBlockChain;
import bisq.core.dao.blockchain.ReadableBsqBlockChain;
import bisq.core.dao.blockchain.vo.BsqBlock;
import bisq.core.dao.param.DaoParamService;
import bisq.core.dao.vote.PeriodService;
import bisq.core.dao.vote.proposal.MyProposalService;
import bisq.core.dao.vote.proposal.Proposal;
import bisq.core.dao.vote.proposal.ProposalListService;
import bisq.core.dao.vote.proposal.ProposalPayload;
import bisq.core.dao.vote.proposal.ProposalService;
import bisq.core.locale.Res;
import bisq.common.UserThread;
import javax.inject.Inject;
import javafx.scene.Node;
@ -71,11 +69,13 @@ import java.util.List;
import java.util.stream.Collectors;
@FxmlView
public abstract class BaseProposalView extends ActivatableView<GridPane, Void> implements BsqBlockChain.Listener {
public abstract class BaseProposalView extends ActivatableView<GridPane, Void> {
protected final ProposalService proposalService;
protected final MyProposalService myProposalService;
protected final ReadableBsqBlockChain readableBsqBlockChain;
protected final DaoParamService daoParamService;
protected final ProposalListService proposalListService;
protected final ProposalService proposalService;
protected final BsqWalletService bsqWalletService;
protected final BsqFormatter bsqFormatter;
protected final BSFormatter btcFormatter;
@ -102,13 +102,17 @@ public abstract class BaseProposalView extends ActivatableView<GridPane, Void> i
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
protected BaseProposalView(ProposalService proposalService,
protected BaseProposalView(MyProposalService myProposalService,
ProposalListService proposalListService,
ProposalService proposalService,
BsqWalletService bsqWalletService,
ReadableBsqBlockChain readableBsqBlockChain,
DaoParamService daoParamService,
PeriodService periodService,
BsqFormatter bsqFormatter,
BSFormatter btcFormatter) {
this.myProposalService = myProposalService;
this.proposalListService = proposalListService;
this.proposalService = proposalService;
this.bsqWalletService = bsqWalletService;
this.readableBsqBlockChain = readableBsqBlockChain;
@ -135,8 +139,6 @@ public abstract class BaseProposalView extends ActivatableView<GridPane, Void> i
selectedProposalSubscription = EasyBind.subscribe(proposalTableView.getSelectionModel().selectedItemProperty(), this::onSelectProposal);
periodService.getPhaseProperty().addListener(phaseChangeListener);
readableBsqBlockChain.addListener(this);
proposalService.getObservableList().addListener(proposalListChangeListener);
onPhaseChanged(periodService.getPhaseProperty().get());
@ -151,8 +153,6 @@ public abstract class BaseProposalView extends ActivatableView<GridPane, Void> i
selectedProposalSubscription.unsubscribe();
periodService.getPhaseProperty().removeListener(phaseChangeListener);
readableBsqBlockChain.removeListener(this);
proposalService.getObservableList().removeListener(proposalListChangeListener);
sortedList.comparatorProperty().unbind();
@ -162,17 +162,6 @@ public abstract class BaseProposalView extends ActivatableView<GridPane, Void> i
}
///////////////////////////////////////////////////////////////////////////////////////////
// BsqBlockChain.Listener
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onBlockAdded(BsqBlock bsqBlock) {
// Need delay otherwise we modify list while dispatching and cause a ConcurrentModificationException
UserThread.execute(this::updateProposalList);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Create views
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -39,7 +39,9 @@ import bisq.core.dao.vote.BooleanVote;
import bisq.core.dao.vote.PeriodService;
import bisq.core.dao.vote.blindvote.BlindVoteConsensus;
import bisq.core.dao.vote.blindvote.BlindVoteService;
import bisq.core.dao.vote.proposal.MyProposalService;
import bisq.core.dao.vote.proposal.Proposal;
import bisq.core.dao.vote.proposal.ProposalListService;
import bisq.core.dao.vote.proposal.ProposalService;
import bisq.core.locale.Res;
@ -86,7 +88,9 @@ public class ActiveProposalsView extends BaseProposalView implements BsqBalanceL
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private ActiveProposalsView(ProposalService voteRequestManger,
private ActiveProposalsView(MyProposalService myProposalService,
ProposalListService proposalListService,
ProposalService proposalService,
PeriodService periodService,
BlindVoteService blindVoteService,
BsqWalletService bsqWalletService,
@ -94,8 +98,9 @@ public class ActiveProposalsView extends BaseProposalView implements BsqBalanceL
DaoParamService daoParamService,
BsqFormatter bsqFormatter,
BSFormatter btcFormatter) {
super(voteRequestManger, bsqWalletService, readableBsqBlockChain, daoParamService, periodService, bsqFormatter,
btcFormatter);
super(myProposalService, proposalListService, proposalService, bsqWalletService, readableBsqBlockChain,
daoParamService, periodService, bsqFormatter, btcFormatter);
this.blindVoteService = blindVoteService;
}
@ -113,6 +118,7 @@ public class ActiveProposalsView extends BaseProposalView implements BsqBalanceL
protected void activate() {
super.activate();
proposalListService.getActiveOrMyUnconfirmedProposals().addListener(proposalListChangeListener);
bsqWalletService.addBsqBalanceListener(this);
onUpdateBalances(bsqWalletService.getAvailableBalance(),
@ -163,6 +169,7 @@ public class ActiveProposalsView extends BaseProposalView implements BsqBalanceL
protected void deactivate() {
super.deactivate();
proposalListService.getActiveOrMyUnconfirmedProposals().removeListener(proposalListChangeListener);
bsqWalletService.removeBsqBalanceListener(this);
}
@ -326,7 +333,7 @@ public class ActiveProposalsView extends BaseProposalView implements BsqBalanceL
@Override
protected void updateProposalList() {
doUpdateProposalList(proposalService.getActiveOrMyUnconfirmedProposals());
doUpdateProposalList(proposalListService.getActiveOrMyUnconfirmedProposals());
}
private void updateStateAfterVote() {
@ -343,7 +350,7 @@ public class ActiveProposalsView extends BaseProposalView implements BsqBalanceL
}
private void onRemove() {
if (proposalService.removeProposal(selectedProposalListItem.getProposal()))
if (myProposalService.removeProposal(selectedProposalListItem.getProposal()))
hideProposalDisplay();
else
new Popup<>().warning(Res.get("dao.proposal.active.remove.failed")).show();

View file

@ -26,6 +26,8 @@ import bisq.core.btc.wallet.BsqWalletService;
import bisq.core.dao.blockchain.ReadableBsqBlockChain;
import bisq.core.dao.param.DaoParamService;
import bisq.core.dao.vote.PeriodService;
import bisq.core.dao.vote.proposal.MyProposalService;
import bisq.core.dao.vote.proposal.ProposalListService;
import bisq.core.dao.vote.proposal.ProposalService;
import javax.inject.Inject;
@ -38,15 +40,18 @@ public class ClosedProposalsView extends BaseProposalView {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private ClosedProposalsView(ProposalService proposalService,
private ClosedProposalsView(MyProposalService myProposalService,
ProposalListService proposalListService,
ProposalService proposalService,
PeriodService periodService,
BsqWalletService bsqWalletService,
ReadableBsqBlockChain readableBsqBlockChain,
DaoParamService daoParamService,
BsqFormatter bsqFormatter,
BSFormatter bsFormatter) {
super(proposalService, bsqWalletService, readableBsqBlockChain, daoParamService, periodService,
bsqFormatter, bsFormatter);
BSFormatter btcFormatter) {
super(myProposalService, proposalListService, proposalService, bsqWalletService, readableBsqBlockChain,
daoParamService, periodService, bsqFormatter, btcFormatter);
}
@Override
@ -60,16 +65,18 @@ public class ClosedProposalsView extends BaseProposalView {
@Override
protected void activate() {
super.activate();
proposalListService.getClosedProposals().addListener(proposalListChangeListener);
}
@Override
protected void deactivate() {
super.deactivate();
proposalListService.getClosedProposals().removeListener(proposalListChangeListener);
}
@Override
protected void updateProposalList() {
doUpdateProposalList(proposalService.getClosedProposals());
doUpdateProposalList(proposalListService.getClosedProposals());
}
}

View file

@ -33,9 +33,9 @@ import bisq.core.btc.wallet.InsufficientBsqException;
import bisq.core.btc.wallet.WalletsSetup;
import bisq.core.dao.blockchain.ReadableBsqBlockChain;
import bisq.core.dao.param.DaoParamService;
import bisq.core.dao.vote.proposal.MyProposalService;
import bisq.core.dao.vote.proposal.Proposal;
import bisq.core.dao.vote.proposal.ProposalConsensus;
import bisq.core.dao.vote.proposal.ProposalService;
import bisq.core.dao.vote.proposal.ProposalType;
import bisq.core.dao.vote.proposal.ValidationException;
import bisq.core.dao.vote.proposal.compensation.CompensationRequestPayload;
@ -85,7 +85,7 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> {
private final WalletsSetup walletsSetup;
private final P2PService p2PService;
private final FeeService feeService;
private final ProposalService proposalService;
private final MyProposalService myProposalService;
private final CompensationRequestService compensationRequestService;
private final GenericProposalService genericProposalService;
private final ReadableBsqBlockChain readableBsqBlockChain;
@ -106,7 +106,7 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> {
WalletsSetup walletsSetup,
P2PService p2PService,
FeeService feeService,
ProposalService proposalService,
MyProposalService myProposalService,
CompensationRequestService compensationRequestService,
GenericProposalService genericProposalService,
ReadableBsqBlockChain readableBsqBlockChain,
@ -117,7 +117,7 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> {
this.walletsSetup = walletsSetup;
this.p2PService = p2PService;
this.feeService = feeService;
this.proposalService = proposalService;
this.myProposalService = myProposalService;
this.compensationRequestService = compensationRequestService;
this.genericProposalService = genericProposalService;
this.readableBsqBlockChain = readableBsqBlockChain;
@ -200,7 +200,7 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> {
}
private void publishProposal(Proposal proposal) {
proposalService.publishProposal(proposal,
myProposalService.publishProposal(proposal,
() -> {
proposalDisplay.clearForm();
proposalTypeComboBox.getSelectionModel().clearSelection();

View file

@ -36,7 +36,9 @@ import bisq.core.dao.vote.BooleanVote;
import bisq.core.dao.vote.PeriodService;
import bisq.core.dao.vote.Vote;
import bisq.core.dao.vote.myvote.MyVoteService;
import bisq.core.dao.vote.proposal.MyProposalService;
import bisq.core.dao.vote.proposal.ProposalList;
import bisq.core.dao.vote.proposal.ProposalListService;
import bisq.core.dao.vote.proposal.ProposalService;
import bisq.core.locale.Res;
import bisq.core.user.Preferences;
@ -74,7 +76,6 @@ import java.util.stream.Collectors;
@FxmlView
public class MyVotesView extends BaseProposalView {
private final MyVoteService myVoteService;
private final ReadableBsqBlockChain readableBsqBlockChain;
private final Preferences preferences;
private final ObservableList<VoteListItem> voteListItems = FXCollections.observableArrayList();
@ -89,19 +90,21 @@ public class MyVotesView extends BaseProposalView {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private MyVotesView(ProposalService voteRequestManger,
private MyVotesView(MyProposalService myProposalService,
ProposalListService proposalListService,
ProposalService proposalService,
PeriodService periodService,
MyVoteService myVoteService,
BsqWalletService bsqWalletService,
ReadableBsqBlockChain readableBsqBlockChain,
DaoParamService daoParamService,
Preferences preferences,
BsqFormatter bsqFormatter,
BSFormatter btcFormatter) {
super(voteRequestManger, bsqWalletService, readableBsqBlockChain, daoParamService, periodService, bsqFormatter,
btcFormatter);
BSFormatter btcFormatter,
MyVoteService myVoteService,
Preferences preferences) {
super(myProposalService, proposalListService, proposalService, bsqWalletService, readableBsqBlockChain,
daoParamService, periodService, bsqFormatter, btcFormatter);
this.myVoteService = myVoteService;
this.readableBsqBlockChain = readableBsqBlockChain;
this.preferences = preferences;
}