Merge pull request #5795 from chimp1984/optimize-dao-charts-7

Optimize DAO charts [7]
This commit is contained in:
Christoph Atteneder 2021-11-09 20:41:36 +01:00 committed by GitHub
commit 60526cc321
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 321 additions and 168 deletions

View file

@ -79,7 +79,7 @@ public class ClockWatcher {
} }
} }
public void stop() { public void shutDown() {
timer.stop(); timer.stop();
timer = null; timer = null;
counter = 0; counter = 0;

View file

@ -31,6 +31,7 @@ import ch.qos.logback.core.util.FileSize;
public class Log { public class Log {
private static Logger logbackLogger; private static Logger logbackLogger;
public static final Level DEFAULT_LOG_LEVEL = Level.INFO;
public static void setLevel(Level logLevel) { public static void setLevel(Level logLevel) {
logbackLogger.setLevel(logLevel); logbackLogger.setLevel(logLevel);
@ -67,23 +68,7 @@ public class Log {
logbackLogger = loggerContext.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); logbackLogger = loggerContext.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
logbackLogger.addAppender(appender); logbackLogger.addAppender(appender);
logbackLogger.setLevel(Level.INFO); logbackLogger.setLevel(DEFAULT_LOG_LEVEL);
// log errors in separate file
// not working as expected still.... damn logback...
/* FileAppender errorAppender = new FileAppender();
errorAppender.setEncoder(encoder);
errorAppender.setName("Error");
errorAppender.setContext(loggerContext);
errorAppender.setFile(fileName + "_error.log");
LevelFilter levelFilter = new LevelFilter();
levelFilter.setLevel(Level.ERROR);
levelFilter.setOnMatch(FilterReply.ACCEPT);
levelFilter.setOnMismatch(FilterReply.DENY);
levelFilter.start();
errorAppender.addFilter(levelFilter);
errorAppender.start();
logbackLogger.addAppender(errorAppender);*/
} }
public static void setCustomLogLevel(String pattern, Level logLevel) { public static void setCustomLogLevel(String pattern, Level logLevel) {

View file

@ -33,6 +33,7 @@ import bisq.core.trade.txproof.xmr.XmrTxProofService;
import bisq.network.p2p.P2PService; import bisq.network.p2p.P2PService;
import bisq.common.ClockWatcher;
import bisq.common.UserThread; import bisq.common.UserThread;
import bisq.common.app.AppModule; import bisq.common.app.AppModule;
import bisq.common.config.BisqHelpFormatter; import bisq.common.config.BisqHelpFormatter;
@ -228,6 +229,7 @@ public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSet
} }
try { try {
injector.getInstance(ClockWatcher.class).shutDown();
injector.getInstance(OpenBsqSwapOfferService.class).shutDown(); injector.getInstance(OpenBsqSwapOfferService.class).shutDown();
injector.getInstance(PriceFeedService.class).shutDown(); injector.getInstance(PriceFeedService.class).shutDown();
injector.getInstance(ArbitratorManager.class).shutDown(); injector.getInstance(ArbitratorManager.class).shutDown();

View file

@ -73,6 +73,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream; import java.util.stream.Stream;
import lombok.Setter; import lombok.Setter;
@ -107,8 +108,9 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
private int maxDataPointsForShowingSymbols = 100; private int maxDataPointsForShowingSymbols = 100;
private ChangeListener<Number> yAxisWidthListener; private ChangeListener<Number> yAxisWidthListener;
private EventHandler<MouseEvent> dividerMouseDraggedEventHandler; private EventHandler<MouseEvent> dividerMouseDraggedEventHandler;
private StringProperty fromProperty = new SimpleStringProperty(); private final StringProperty fromProperty = new SimpleStringProperty();
private StringProperty toProperty = new SimpleStringProperty(); private final StringProperty toProperty = new SimpleStringProperty();
private boolean dataApplied;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -219,19 +221,14 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
@Override @Override
public void activate() { public void activate() {
timelineNavigation.setDividerPositions(model.getDividerPositions()[0], model.getDividerPositions()[1]); timelineNavigation.setDividerPositions(model.getDividerPositions()[0], model.getDividerPositions()[1]);
UserThread.execute(this::applyTimeLineNavigationLabels);
UserThread.execute(this::onTimelineChanged);
TemporalAdjuster temporalAdjuster = model.getTemporalAdjuster(); TemporalAdjuster temporalAdjuster = model.getTemporalAdjuster();
applyTemporalAdjuster(temporalAdjuster); applyTemporalAdjuster(temporalAdjuster);
findTimeIntervalToggleByTemporalAdjuster(temporalAdjuster).ifPresent(timeIntervalToggleGroup::selectToggle); findTimeIntervalToggleByTemporalAdjuster(temporalAdjuster).ifPresent(timeIntervalToggleGroup::selectToggle);
defineAndAddActiveSeries(); defineAndAddActiveSeries();
applyData();
initBoundsForTimelineNavigation(); initBoundsForTimelineNavigation();
updateChartAfterDataChange();
// Apply listeners and handlers // Apply listeners and handlers
root.widthProperty().addListener(widthListener); root.widthProperty().addListener(widthListener);
xAxis.getChildrenUnmodifiable().addListener(nodeListChangeListener); xAxis.getChildrenUnmodifiable().addListener(nodeListChangeListener);
@ -555,7 +552,7 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
chart.getData().add(series); chart.getData().add(series);
activeSeries.add(series); activeSeries.add(series);
legendToggleBySeriesName.get(getSeriesId(series)).setSelected(true); legendToggleBySeriesName.get(getSeriesId(series)).setSelected(true);
updateChartAfterDataChange(); applyDataAndUpdate();
} }
@ -563,7 +560,17 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
// Data // Data
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
protected abstract void applyData(); protected abstract CompletableFuture<Boolean> applyData();
private void applyDataAndUpdate() {
long ts = System.currentTimeMillis();
applyData().whenComplete((r, t) -> {
log.debug("applyData took {}", System.currentTimeMillis() - ts);
long ts2 = System.currentTimeMillis();
updateChartAfterDataChange();
log.debug("updateChartAfterDataChange took {}", System.currentTimeMillis() - ts2);
});
}
/** /**
* Implementations define which series will be used for setBoundsForTimelineNavigation * Implementations define which series will be used for setBoundsForTimelineNavigation
@ -589,16 +596,14 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
TemporalAdjusterModel.Interval interval = (TemporalAdjusterModel.Interval) newValue.getUserData(); TemporalAdjusterModel.Interval interval = (TemporalAdjusterModel.Interval) newValue.getUserData();
applyTemporalAdjuster(interval.getAdjuster()); applyTemporalAdjuster(interval.getAdjuster());
model.invalidateCache(); model.invalidateCache();
applyData(); applyDataAndUpdate();
updateChartAfterDataChange();
} }
private void onTimelineChanged() { private void onTimelineChanged() {
updateTimeLinePositions(); updateTimeLinePositions();
model.invalidateCache(); model.invalidateCache();
applyData(); applyDataAndUpdate(); //3
updateChartAfterDataChange();
} }
private void updateTimeLinePositions() { private void updateTimeLinePositions() {
@ -636,8 +641,7 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
if (isSelected) { if (isSelected) {
chart.getData().add(series); chart.getData().add(series);
activeSeries.add(series); activeSeries.add(series);
//model.invalidateCache(); applyDataAndUpdate();
applyData();
if (isRadioButtonBehaviour) { if (isRadioButtonBehaviour) {
// We support different y-axis formats only if isRadioButtonBehaviour is set, otherwise we would get // We support different y-axis formats only if isRadioButtonBehaviour is set, otherwise we would get
@ -647,9 +651,8 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
} else if (!isRadioButtonBehaviour) { // if isRadioButtonBehaviour we have removed it already via the code above } else if (!isRadioButtonBehaviour) { // if isRadioButtonBehaviour we have removed it already via the code above
chart.getData().remove(series); chart.getData().remove(series);
activeSeries.remove(series); activeSeries.remove(series);
updateChartAfterDataChange();
} }
updateChartAfterDataChange();
} }
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -771,4 +774,23 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
protected String getSeriesId(XYChart.Series<Number, Number> series) { protected String getSeriesId(XYChart.Series<Number, Number> series) {
return series.getName(); return series.getName();
} }
protected void mapToUserThread(Runnable command) {
UserThread.execute(() -> {
command.run();
onDataApplied();
});
}
// For the async handling we need to wait until we get the data applied and then still delay a bit otherwise
// the UI does not get rendered at first start
protected void onDataApplied() {
if (!dataApplied) {
dataApplied = true;
UserThread.execute(() -> {
applyTimeLineNavigationLabels();
updateTimeLinePositions();
});
}
}
} }

View file

@ -21,6 +21,8 @@ import bisq.desktop.components.chart.ChartView;
import bisq.core.locale.Res; import bisq.core.locale.Res;
import bisq.common.util.CompletableFutureUtils;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.scene.chart.XYChart; import javafx.scene.chart.XYChart;
@ -29,16 +31,20 @@ import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ReadOnlyDoubleProperty; import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.SimpleDoubleProperty;
import javafx.collections.ObservableList;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
public class PriceChartView extends ChartView<PriceChartViewModel> { public class PriceChartView extends ChartView<PriceChartViewModel> {
private XYChart.Series<Number, Number> seriesBsqUsdPrice, seriesBsqBtcPrice, seriesBtcUsdPrice; private XYChart.Series<Number, Number> seriesBsqUsdPrice, seriesBsqBtcPrice, seriesBtcUsdPrice;
private DoubleProperty averageBsqUsdPriceProperty = new SimpleDoubleProperty(); private final DoubleProperty averageBsqUsdPriceProperty = new SimpleDoubleProperty();
private DoubleProperty averageBsqBtcPriceProperty = new SimpleDoubleProperty(); private final DoubleProperty averageBsqBtcPriceProperty = new SimpleDoubleProperty();
@Inject @Inject
public PriceChartView(PriceChartViewModel model) { public PriceChartView(PriceChartViewModel model) {
@ -121,38 +127,80 @@ public class PriceChartView extends ChartView<PriceChartViewModel> {
onSetYAxisFormatter(seriesBsqUsdPrice); onSetYAxisFormatter(seriesBsqUsdPrice);
} }
@Override
protected void activateSeries(XYChart.Series<Number, Number> series) {
super.activateSeries(series);
String seriesId = getSeriesId(series);
if (seriesId.equals(getSeriesId(seriesBsqUsdPrice))) {
seriesBsqUsdPrice.getData().setAll(model.getBsqUsdPriceChartData());
} else if (seriesId.equals(getSeriesId(seriesBsqBtcPrice))) {
seriesBsqBtcPrice.getData().setAll(model.getBsqBtcPriceChartData());
} else if (seriesId.equals(getSeriesId(seriesBtcUsdPrice))) {
seriesBtcUsdPrice.getData().setAll(model.getBtcUsdPriceChartData());
}
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Data // Data
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Override @Override
protected void applyData() { protected CompletableFuture<Boolean> applyData() {
List<CompletableFuture<Boolean>> allFutures = new ArrayList<>();
if (activeSeries.contains(seriesBsqUsdPrice)) { if (activeSeries.contains(seriesBsqUsdPrice)) {
seriesBsqUsdPrice.getData().setAll(model.getBsqUsdPriceChartData()); CompletableFuture<Boolean> task1Done = new CompletableFuture<>();
allFutures.add(task1Done);
applyBsqUsdPriceChartDataAsync(task1Done);
} }
if (activeSeries.contains(seriesBsqBtcPrice)) { if (activeSeries.contains(seriesBsqBtcPrice)) {
seriesBsqBtcPrice.getData().setAll(model.getBsqBtcPriceChartData()); CompletableFuture<Boolean> task2Done = new CompletableFuture<>();
allFutures.add(task2Done);
applyBsqBtcPriceChartData(task2Done);
} }
if (activeSeries.contains(seriesBtcUsdPrice)) { if (activeSeries.contains(seriesBtcUsdPrice)) {
seriesBtcUsdPrice.getData().setAll(model.getBtcUsdPriceChartData()); CompletableFuture<Boolean> task3Done = new CompletableFuture<>();
allFutures.add(task3Done);
applyBtcUsdPriceChartData(task3Done);
} }
averageBsqBtcPriceProperty.set(model.averageBsqBtcPrice()); CompletableFuture<Boolean> task4Done = new CompletableFuture<>();
averageBsqUsdPriceProperty.set(model.averageBsqUsdPrice()); allFutures.add(task4Done);
model.averageBsqBtcPrice()
.whenComplete((data, t) ->
mapToUserThread(() -> {
averageBsqBtcPriceProperty.set(data);
task4Done.complete(true);
}));
CompletableFuture<Boolean> task5Done = new CompletableFuture<>();
allFutures.add(task5Done);
model.averageBsqUsdPrice()
.whenComplete((data, t) ->
mapToUserThread(() -> {
averageBsqUsdPriceProperty.set(data);
task5Done.complete(true);
}));
return CompletableFutureUtils.allOf(allFutures).thenApply(e -> {
return true;
});
}
private void applyBsqUsdPriceChartDataAsync(CompletableFuture<Boolean> completeFuture) {
model.getBsqUsdPriceChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
ObservableList<XYChart.Data<Number, Number>> data1 = seriesBsqUsdPrice.getData();
data1.setAll(data);
completeFuture.complete(true);
})
);
}
private void applyBtcUsdPriceChartData(CompletableFuture<Boolean> completeFuture) {
model.getBtcUsdPriceChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesBtcUsdPrice.getData().setAll(data);
completeFuture.complete(true);
}));
}
private void applyBsqBtcPriceChartData(CompletableFuture<Boolean> completeFuture) {
model.getBsqBtcPriceChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesBsqBtcPrice.getData().setAll(data);
completeFuture.complete(true);
}));
} }
} }

View file

@ -32,6 +32,7 @@ import javafx.util.StringConverter;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function; import java.util.function.Function;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -53,12 +54,12 @@ public class PriceChartViewModel extends ChartViewModel<PriceChartDataModel> {
// Average price from timeline selection // Average price from timeline selection
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
double averageBsqUsdPrice() { CompletableFuture<Double> averageBsqUsdPrice() {
return dataModel.averageBsqUsdPrice(); return CompletableFuture.supplyAsync(() -> dataModel.averageBsqUsdPrice());
} }
double averageBsqBtcPrice() { CompletableFuture<Double> averageBsqBtcPrice() {
return dataModel.averageBsqBtcPrice(); return CompletableFuture.supplyAsync(() -> dataModel.averageBsqBtcPrice());
} }
@ -66,16 +67,17 @@ public class PriceChartViewModel extends ChartViewModel<PriceChartDataModel> {
// Chart data // Chart data
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
List<XYChart.Data<Number, Number>> getBsqUsdPriceChartData() {
return toChartDoubleData(dataModel.getBsqUsdPriceByInterval()); CompletableFuture<List<XYChart.Data<Number, Number>>> getBsqUsdPriceChartData() {
return CompletableFuture.supplyAsync(() -> toChartDoubleData(dataModel.getBsqUsdPriceByInterval()));
} }
List<XYChart.Data<Number, Number>> getBsqBtcPriceChartData() { CompletableFuture<List<XYChart.Data<Number, Number>>> getBsqBtcPriceChartData() {
return toChartDoubleData(dataModel.getBsqBtcPriceByInterval()); return CompletableFuture.supplyAsync(() -> toChartDoubleData(dataModel.getBsqBtcPriceByInterval()));
} }
List<XYChart.Data<Number, Number>> getBtcUsdPriceChartData() { CompletableFuture<List<XYChart.Data<Number, Number>>> getBtcUsdPriceChartData() {
return toChartDoubleData(dataModel.getBtcUsdPriceByInterval()); return CompletableFuture.supplyAsync(() -> toChartDoubleData(dataModel.getBtcUsdPriceByInterval()));
} }

View file

@ -21,6 +21,8 @@ import bisq.desktop.components.chart.ChartView;
import bisq.core.locale.Res; import bisq.core.locale.Res;
import bisq.common.util.CompletableFutureUtils;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.scene.chart.XYChart; import javafx.scene.chart.XYChart;
@ -29,8 +31,10 @@ import javafx.beans.property.LongProperty;
import javafx.beans.property.ReadOnlyLongProperty; import javafx.beans.property.ReadOnlyLongProperty;
import javafx.beans.property.SimpleLongProperty; import javafx.beans.property.SimpleLongProperty;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -38,8 +42,8 @@ import lombok.extern.slf4j.Slf4j;
public class VolumeChartView extends ChartView<VolumeChartViewModel> { public class VolumeChartView extends ChartView<VolumeChartViewModel> {
private XYChart.Series<Number, Number> seriesUsdVolume, seriesBtcVolume; private XYChart.Series<Number, Number> seriesUsdVolume, seriesBtcVolume;
private LongProperty usdVolumeProperty = new SimpleLongProperty(); private final LongProperty usdVolumeProperty = new SimpleLongProperty();
private LongProperty btcVolumeProperty = new SimpleLongProperty(); private final LongProperty btcVolumeProperty = new SimpleLongProperty();
@Inject @Inject
public VolumeChartView(VolumeChartViewModel model) { public VolumeChartView(VolumeChartViewModel model) {
@ -117,32 +121,61 @@ public class VolumeChartView extends ChartView<VolumeChartViewModel> {
onSetYAxisFormatter(seriesUsdVolume); onSetYAxisFormatter(seriesUsdVolume);
} }
@Override
protected void activateSeries(XYChart.Series<Number, Number> series) {
super.activateSeries(series);
if (getSeriesId(series).equals(getSeriesId(seriesUsdVolume))) {
seriesUsdVolume.getData().setAll(model.getUsdVolumeChartData());
} else if (getSeriesId(series).equals(getSeriesId(seriesBtcVolume))) {
seriesBtcVolume.getData().setAll(model.getBtcVolumeChartData());
}
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Data // Data
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Override @Override
protected void applyData() { protected CompletableFuture<Boolean> applyData() {
List<CompletableFuture<Boolean>> allFutures = new ArrayList<>();
if (activeSeries.contains(seriesUsdVolume)) { if (activeSeries.contains(seriesUsdVolume)) {
seriesUsdVolume.getData().setAll(model.getUsdVolumeChartData()); CompletableFuture<Boolean> task1Done = new CompletableFuture<>();
allFutures.add(task1Done);
applyUsdVolumeChartData(task1Done);
} }
if (activeSeries.contains(seriesBtcVolume)) { if (activeSeries.contains(seriesBtcVolume)) {
seriesBtcVolume.getData().setAll(model.getBtcVolumeChartData()); CompletableFuture<Boolean> task2Done = new CompletableFuture<>();
allFutures.add(task2Done);
applyBtcVolumeChartData(task2Done);
} }
usdVolumeProperty.set(model.getUsdVolume()); CompletableFuture<Boolean> task3Done = new CompletableFuture<>();
btcVolumeProperty.set(model.getBtcVolume()); allFutures.add(task3Done);
model.getUsdVolume()
.whenComplete((data, t) ->
mapToUserThread(() -> {
usdVolumeProperty.set(data);
task3Done.complete(true);
}));
CompletableFuture<Boolean> task4Done = new CompletableFuture<>();
allFutures.add(task4Done);
model.getBtcVolume()
.whenComplete((data, t) ->
mapToUserThread(() -> {
btcVolumeProperty.set(data);
task4Done.complete(true);
}));
return CompletableFutureUtils.allOf(allFutures).thenApply(e -> true);
}
private void applyBtcVolumeChartData(CompletableFuture<Boolean> completeFuture) {
model.getBtcVolumeChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesBtcVolume.getData().setAll(data);
completeFuture.complete(true);
}));
}
private void applyUsdVolumeChartData(CompletableFuture<Boolean> completeFuture) {
model.getUsdVolumeChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesUsdVolume.getData().setAll(data);
completeFuture.complete(true);
}));
} }
} }

View file

@ -32,6 +32,7 @@ import javafx.util.StringConverter;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function; import java.util.function.Function;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -54,12 +55,12 @@ public class VolumeChartViewModel extends ChartViewModel<VolumeChartDataModel> {
// Total amounts // Total amounts
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
long getUsdVolume() { CompletableFuture<Long> getUsdVolume() {
return dataModel.getUsdVolume(); return CompletableFuture.supplyAsync(dataModel::getUsdVolume);
} }
long getBtcVolume() { CompletableFuture<Long> getBtcVolume() {
return dataModel.getBtcVolume(); return CompletableFuture.supplyAsync(dataModel::getBtcVolume);
} }
@ -67,12 +68,12 @@ public class VolumeChartViewModel extends ChartViewModel<VolumeChartDataModel> {
// Chart data // Chart data
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
List<XYChart.Data<Number, Number>> getUsdVolumeChartData() { CompletableFuture<List<XYChart.Data<Number, Number>>> getUsdVolumeChartData() {
return toChartLongData(dataModel.getUsdVolumeByInterval()); return CompletableFuture.supplyAsync(() -> toChartLongData(dataModel.getUsdVolumeByInterval()));
} }
List<XYChart.Data<Number, Number>> getBtcVolumeChartData() { CompletableFuture<List<XYChart.Data<Number, Number>>> getBtcVolumeChartData() {
return toChartLongData(dataModel.getBtcVolumeByInterval()); return CompletableFuture.supplyAsync(() -> toChartLongData(dataModel.getBtcVolumeByInterval()));
} }

View file

@ -21,6 +21,8 @@ import bisq.desktop.components.chart.ChartView;
import bisq.core.locale.Res; import bisq.core.locale.Res;
import bisq.common.util.CompletableFutureUtils;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.scene.chart.XYChart; import javafx.scene.chart.XYChart;
@ -29,17 +31,19 @@ import javafx.beans.property.LongProperty;
import javafx.beans.property.ReadOnlyLongProperty; import javafx.beans.property.ReadOnlyLongProperty;
import javafx.beans.property.SimpleLongProperty; import javafx.beans.property.SimpleLongProperty;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
public class DaoChartView extends ChartView<DaoChartViewModel> { public class DaoChartView extends ChartView<DaoChartViewModel> {
private LongProperty compensationAmountProperty = new SimpleLongProperty(); private final LongProperty compensationAmountProperty = new SimpleLongProperty();
private LongProperty reimbursementAmountProperty = new SimpleLongProperty(); private final LongProperty reimbursementAmountProperty = new SimpleLongProperty();
private LongProperty bsqTradeFeeAmountProperty = new SimpleLongProperty(); private final LongProperty bsqTradeFeeAmountProperty = new SimpleLongProperty();
private LongProperty proofOfBurnAmountProperty = new SimpleLongProperty(); private final LongProperty proofOfBurnAmountProperty = new SimpleLongProperty();
private XYChart.Series<Number, Number> seriesBsqTradeFee, seriesProofOfBurn, seriesCompensation, private XYChart.Series<Number, Number> seriesBsqTradeFee, seriesProofOfBurn, seriesCompensation,
seriesReimbursement, seriesTotalIssued, seriesTotalBurned; seriesReimbursement, seriesTotalIssued, seriesTotalBurned;
@ -134,78 +138,135 @@ public class DaoChartView extends ChartView<DaoChartViewModel> {
activateSeries(seriesTotalBurned); activateSeries(seriesTotalBurned);
} }
@Override
protected void activateSeries(XYChart.Series<Number, Number> series) {
super.activateSeries(series);
if (getSeriesId(series).equals(getSeriesId(seriesTotalIssued))) {
applyTotalIssued();
} else if (getSeriesId(series).equals(getSeriesId(seriesCompensation))) {
applyCompensation();
} else if (getSeriesId(series).equals(getSeriesId(seriesReimbursement))) {
applyReimbursement();
} else if (getSeriesId(series).equals(getSeriesId(seriesTotalBurned))) {
applyTotalBurned();
} else if (getSeriesId(series).equals(getSeriesId(seriesBsqTradeFee))) {
applyBsqTradeFee();
} else if (getSeriesId(series).equals(getSeriesId(seriesProofOfBurn))) {
applyProofOfBurn();
}
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Data // Data
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Override @Override
protected void applyData() { protected CompletableFuture<Boolean> applyData() {
List<CompletableFuture<Boolean>> allFutures = new ArrayList<>();
if (activeSeries.contains(seriesTotalIssued)) { if (activeSeries.contains(seriesTotalIssued)) {
applyTotalIssued(); CompletableFuture<Boolean> task1Done = new CompletableFuture<>();
allFutures.add(task1Done);
applyTotalIssued(task1Done);
} }
if (activeSeries.contains(seriesCompensation)) { if (activeSeries.contains(seriesCompensation)) {
applyCompensation(); CompletableFuture<Boolean> task2Done = new CompletableFuture<>();
allFutures.add(task2Done);
applyCompensation(task2Done);
} }
if (activeSeries.contains(seriesReimbursement)) { if (activeSeries.contains(seriesReimbursement)) {
applyReimbursement(); CompletableFuture<Boolean> task3Done = new CompletableFuture<>();
allFutures.add(task3Done);
applyReimbursement(task3Done);
} }
if (activeSeries.contains(seriesTotalBurned)) { if (activeSeries.contains(seriesTotalBurned)) {
applyTotalBurned(); CompletableFuture<Boolean> task4Done = new CompletableFuture<>();
allFutures.add(task4Done);
applyTotalBurned(task4Done);
} }
if (activeSeries.contains(seriesBsqTradeFee)) { if (activeSeries.contains(seriesBsqTradeFee)) {
applyBsqTradeFee(); CompletableFuture<Boolean> task5Done = new CompletableFuture<>();
allFutures.add(task5Done);
applyBsqTradeFee(task5Done);
} }
if (activeSeries.contains(seriesProofOfBurn)) { if (activeSeries.contains(seriesProofOfBurn)) {
applyProofOfBurn(); CompletableFuture<Boolean> task6Done = new CompletableFuture<>();
allFutures.add(task6Done);
applyProofOfBurn(task6Done);
} }
compensationAmountProperty.set(model.getCompensationAmount()); CompletableFuture<Boolean> task7Done = new CompletableFuture<>();
reimbursementAmountProperty.set(model.getReimbursementAmount()); allFutures.add(task7Done);
bsqTradeFeeAmountProperty.set(model.getBsqTradeFeeAmount()); model.getCompensationAmount()
proofOfBurnAmountProperty.set(model.getProofOfBurnAmount()); .whenComplete((data, t) ->
mapToUserThread(() -> {
compensationAmountProperty.set(data);
task7Done.complete(true);
}));
CompletableFuture<Boolean> task8Done = new CompletableFuture<>();
allFutures.add(task8Done);
model.getReimbursementAmount()
.whenComplete((data, t) ->
mapToUserThread(() -> {
reimbursementAmountProperty.set(data);
task8Done.complete(true);
}));
CompletableFuture<Boolean> task9Done = new CompletableFuture<>();
allFutures.add(task9Done);
model.getBsqTradeFeeAmount()
.whenComplete((data, t) ->
mapToUserThread(() -> {
bsqTradeFeeAmountProperty.set(data);
task9Done.complete(true);
}));
CompletableFuture<Boolean> task10Done = new CompletableFuture<>();
allFutures.add(task10Done);
model.getProofOfBurnAmount()
.whenComplete((data, t) ->
mapToUserThread(() -> {
proofOfBurnAmountProperty.set(data);
task10Done.complete(true);
}));
return CompletableFutureUtils.allOf(allFutures).thenApply(e -> true);
} }
private void applyTotalIssued() { private void applyTotalIssued(CompletableFuture<Boolean> completeFuture) {
seriesTotalIssued.getData().setAll(model.getTotalIssuedChartData()); model.getTotalIssuedChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesTotalIssued.getData().setAll(data);
completeFuture.complete(true);
}));
} }
private void applyCompensation() { private void applyCompensation(CompletableFuture<Boolean> completeFuture) {
seriesCompensation.getData().setAll(model.getCompensationChartData()); model.getCompensationChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesCompensation.getData().setAll(data);
completeFuture.complete(true);
}));
} }
private void applyReimbursement() { private void applyReimbursement(CompletableFuture<Boolean> completeFuture) {
seriesReimbursement.getData().setAll(model.getReimbursementChartData()); model.getReimbursementChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesReimbursement.getData().setAll(data);
completeFuture.complete(true);
}));
} }
private void applyTotalBurned() { private void applyTotalBurned(CompletableFuture<Boolean> completeFuture) {
seriesTotalBurned.getData().setAll(model.getTotalBurnedChartData()); model.getTotalBurnedChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesTotalBurned.getData().setAll(data);
completeFuture.complete(true);
}));
} }
private void applyBsqTradeFee() { private void applyBsqTradeFee(CompletableFuture<Boolean> completeFuture) {
seriesBsqTradeFee.getData().setAll(model.getBsqTradeFeeChartData()); model.getBsqTradeFeeChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesBsqTradeFee.getData().setAll(data);
completeFuture.complete(true);
}));
} }
private void applyProofOfBurn() { private void applyProofOfBurn(CompletableFuture<Boolean> completeFuture) {
seriesProofOfBurn.getData().setAll(model.getProofOfBurnChartData()); model.getProofOfBurnChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesProofOfBurn.getData().setAll(data);
completeFuture.complete(true);
}));
} }
} }

View file

@ -31,6 +31,7 @@ import javafx.util.StringConverter;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -53,28 +54,28 @@ public class DaoChartViewModel extends ChartViewModel<DaoChartDataModel> {
// Chart data // Chart data
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
List<XYChart.Data<Number, Number>> getTotalIssuedChartData() { CompletableFuture<List<XYChart.Data<Number, Number>>> getTotalIssuedChartData() {
return toChartData(dataModel.getTotalIssuedByInterval()); return CompletableFuture.supplyAsync(() -> toChartData(dataModel.getTotalIssuedByInterval()));
} }
List<XYChart.Data<Number, Number>> getCompensationChartData() { CompletableFuture<List<XYChart.Data<Number, Number>>> getCompensationChartData() {
return toChartData(dataModel.getCompensationByInterval()); return CompletableFuture.supplyAsync(() -> toChartData(dataModel.getCompensationByInterval()));
} }
List<XYChart.Data<Number, Number>> getReimbursementChartData() { CompletableFuture<List<XYChart.Data<Number, Number>>> getReimbursementChartData() {
return toChartData(dataModel.getReimbursementByInterval()); return CompletableFuture.supplyAsync(() -> toChartData(dataModel.getReimbursementByInterval()));
} }
List<XYChart.Data<Number, Number>> getTotalBurnedChartData() { CompletableFuture<List<XYChart.Data<Number, Number>>> getTotalBurnedChartData() {
return toChartData(dataModel.getTotalBurnedByInterval()); return CompletableFuture.supplyAsync(() -> toChartData(dataModel.getTotalBurnedByInterval()));
} }
List<XYChart.Data<Number, Number>> getBsqTradeFeeChartData() { CompletableFuture<List<XYChart.Data<Number, Number>>> getBsqTradeFeeChartData() {
return toChartData(dataModel.getBsqTradeFeeByInterval()); return CompletableFuture.supplyAsync(() -> toChartData(dataModel.getBsqTradeFeeByInterval()));
} }
List<XYChart.Data<Number, Number>> getProofOfBurnChartData() { CompletableFuture<List<XYChart.Data<Number, Number>>> getProofOfBurnChartData() {
return toChartData(dataModel.getProofOfBurnByInterval()); return CompletableFuture.supplyAsync(() -> toChartData(dataModel.getProofOfBurnByInterval()));
} }
@ -107,19 +108,19 @@ public class DaoChartViewModel extends ChartViewModel<DaoChartDataModel> {
// DaoChartDataModel delegates // DaoChartDataModel delegates
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
long getCompensationAmount() { CompletableFuture<Long> getCompensationAmount() {
return dataModel.getCompensationAmount(); return CompletableFuture.supplyAsync(dataModel::getCompensationAmount);
} }
long getReimbursementAmount() { CompletableFuture<Long> getReimbursementAmount() {
return dataModel.getReimbursementAmount(); return CompletableFuture.supplyAsync(dataModel::getReimbursementAmount);
} }
long getBsqTradeFeeAmount() { CompletableFuture<Long> getBsqTradeFeeAmount() {
return dataModel.getBsqTradeFeeAmount(); return CompletableFuture.supplyAsync(dataModel::getBsqTradeFeeAmount);
} }
long getProofOfBurnAmount() { CompletableFuture<Long> getProofOfBurnAmount() {
return dataModel.getProofOfBurnAmount(); return CompletableFuture.supplyAsync(dataModel::getProofOfBurnAmount);
} }
} }

View file

@ -1064,20 +1064,18 @@ public class P2PDataStorage implements MessageListener, ConnectionListener, Pers
+ newSequenceNumber + " / storedSequenceNumber=" + storedSequenceNumber + " / hashOfData=" + hashOfData.toString());*/ + newSequenceNumber + " / storedSequenceNumber=" + storedSequenceNumber + " / hashOfData=" + hashOfData.toString());*/
return true; return true;
} else if (newSequenceNumber == storedSequenceNumber) { } else if (newSequenceNumber == storedSequenceNumber) {
String msg;
if (newSequenceNumber == 0) { if (newSequenceNumber == 0) {
msg = "Sequence number is equal to the stored one and both are 0." + log.debug("Sequence number is equal to the stored one and both are 0." +
"That is expected for network_messages which never got updated (mailbox msg)."; "That is expected for network_messages which never got updated (mailbox msg).");
} else { } else {
msg = "Sequence number is equal to the stored one. sequenceNumber = " log.debug("Sequence number is equal to the stored one. sequenceNumber = {} / storedSequenceNumber={}",
+ newSequenceNumber + " / storedSequenceNumber=" + storedSequenceNumber; newSequenceNumber, storedSequenceNumber);
} }
log.debug(msg);
return false; return false;
} else { } else {
log.debug("Sequence number is invalid. sequenceNumber = " log.debug("Sequence number is invalid. sequenceNumber = {} / storedSequenceNumber={} " +
+ newSequenceNumber + " / storedSequenceNumber=" + storedSequenceNumber + "\n" + "That can happen if the data owner gets an old delayed data storage message.",
"That can happen if the data owner gets an old delayed data storage message."); newSequenceNumber, storedSequenceNumber);
return false; return false;
} }
} else { } else {