bug6278: added observer pattern for TimeRangeActionsExecutor, too

This commit is contained in:
Axel Uhl committed 2026-07-31 18:47:23 +02:00
1 parent 17afe27cf9
commit 9470d78bbc
7 files changed
+68 -13

No files matched your search

@@ -17,6 +17,7 @@ import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.gwt.client.DateAndTimeFormatterUtil;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.async.TimeRangeActionsExecutor;
import com.sap.sse.gwt.client.player.TimeRangeWithZoomProvider;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
@@ -80,13 +81,15 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
private final Duration initialTimeAfterRaceStartInReplayMode;
public RaceTimePanel(Component<?> parent, ComponentContext<?> context, RaceTimePanelLifecycle componentLifecycle,
UserService userService,
Timer timer, TimeRangeWithZoomProvider timeRangeProvider, StringMessages stringMessages,
RaceTimesInfoProvider raceTimesInfoProvider, boolean canReplayWhileLiveIsPossible, boolean forcePaddingRightToAlignToCharts,
UserService userService, Timer timer, TimeRangeWithZoomProvider timeRangeProvider,
StringMessages stringMessages, RaceTimesInfoProvider raceTimesInfoProvider,
boolean canReplayWhileLiveIsPossible, boolean forcePaddingRightToAlignToCharts,
RegattaAndRaceIdentifier selectedRaceIdentifier, Duration initialTimeAfterRaceStartInReplayMode,
final RaceWithCompetitorsAndBoatsDTO raceDTO, AsyncActionsExecutor pendingServerOperationsCountSupplier) {
final RaceWithCompetitorsAndBoatsDTO raceDTO, AsyncActionsExecutor pendingServerOperationsCountSupplier,
TimeRangeActionsExecutor<?, ?, ?> timeRangeActionsExecutor) {
super(parent, context, timer, timeRangeProvider, stringMessages, canReplayWhileLiveIsPossible,
forcePaddingRightToAlignToCharts, userService, raceDTO, pendingServerOperationsCountSupplier, timeRangeActionsExecutor);
forcePaddingRightToAlignToCharts, userService, raceDTO, pendingServerOperationsCountSupplier,
timeRangeActionsExecutor);
this.raceDTO = raceDTO;
this.componentLifecycle = componentLifecycle;
this.userService = userService;
@@ -25,6 +25,7 @@ import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.util.IntHolder;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.async.TimeRangeActionsExecutor;
import com.sap.sse.gwt.client.controls.slider.SliderBar;
@@ -310,20 +311,40 @@ public class TimePanel<T extends TimePanelSettings> extends AbstractCompositeCom
});
controlsPanel.add(resetZoomButton);
if (pendingServerOperationsCountSupplier != null) {
final IntHolder pendingServerOperationsCount = new IntHolder(0);
final IntHolder pendingTimeRangeActionsCount = new IntHolder(0);
final Label pendingServerOperationsCounter = new Label(getPendingServerOperationsCounterLabelText(pendingServerOperationsCountSupplier));
pendingServerOperationsCounter.addStyleName("timePanel-controls-pendingServerOperationsCounter");
controlsPanel.add(pendingServerOperationsCounter);
pendingServerOperationsCountSupplier.addListener(
newPendingOperationsCount->{
pendingServerOperationsCounter.setText(getPendingServerOperationsCounterLabelText(pendingServerOperationsCountSupplier));
pendingServerOperationsCounter.getElement().getStyle().setProperty("backgroundSize",
"calc("+
(100*pendingServerOperationsCountSupplier.getNumberOfPendingActions()/AsyncActionsExecutor.DEFAULT_MAX_PENDING_CALLS)+"% - 30px) 100%");
pendingServerOperationsCount.value = newPendingOperationsCount;
updatePendingOperationsLabel(pendingServerOperationsCountSupplier, pendingServerOperationsCount,
pendingTimeRangeActionsCount, pendingServerOperationsCounter);
});
if (pendingTimeRangeActionsSupplier != null) {
pendingTimeRangeActionsSupplier.addListener(newPendingTimeRangeActions->{
pendingTimeRangeActionsCount.value = newPendingTimeRangeActions;
updatePendingOperationsLabel(pendingServerOperationsCountSupplier, pendingServerOperationsCount,
pendingTimeRangeActionsCount, pendingServerOperationsCounter);
});
}
}
hideControlsPanel();
}
private void updatePendingOperationsLabel(AsyncActionsExecutor pendingServerOperationsCountSupplier,
final IntHolder pendingServerOperationsCount, final IntHolder pendingTimeRangeActionsCount,
final Label pendingServerOperationsCounter) {
final int EXPECTED_MAX_NUMBER_OF_PENDING_TIME_RANGE_ACTIONS = 10;
final int numberOfPendingServerOperations = pendingServerOperationsCount.value+pendingTimeRangeActionsCount.value;
pendingServerOperationsCounter.setText(stringMessages.pendingServerOperations(numberOfPendingServerOperations));
pendingServerOperationsCounter.getElement().getStyle().setProperty("backgroundSize",
(numberOfPendingServerOperations > 0
? "max(calc("+(100*numberOfPendingServerOperations/(AsyncActionsExecutor.DEFAULT_MAX_PENDING_CALLS+EXPECTED_MAX_NUMBER_OF_PENDING_TIME_RANGE_ACTIONS))+"% - 30px), 10px)"
: "0") + " 100%");
}
private String getPendingServerOperationsCounterLabelText(AsyncActionsExecutor pendingServerOperationsCountSupplier) {
return stringMessages.pendingServerOperations(pendingServerOperationsCountSupplier.getNumberOfPendingActions());
}
@@ -3928,5 +3928,9 @@ public class RaceMap extends AbstractCompositeComponent<RaceMapSettings> impleme
}
}.schedule(500);
}
public TimeRangeActionsExecutor<CompactBoatPositionsDTO, GPSFixDTOWithSpeedWindTackAndLegTypeIterable, Pair<String, DetailType>> getTimeRangeActionsExecutor() {
return timeRangeActionsExecutor;
}
}
@@ -193,7 +193,7 @@ public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingReadEntryP
timer, timeRangeWithZoomProvider, getStringMessages(), /* canReplayWhileLive */ false,
/* isScreenLargeEnoughToOfferChartSupport set to true iff wind chart will be displayed */ raceboardPerspectiveSettings
.isShowWindChart(),
getUserService(), raceDTOProxy, asyncActionsExecutor, timeRangeActionsExecutor) {
getUserService(), raceDTOProxy, asyncActionsExecutor, /* timeRangeActionsExecutor */ null) {
protected boolean isLiveModeToBeMadePossible() {
return true;
}
@@ -441,7 +441,7 @@ public class RaceBoardPanel
timeRangeWithZoomModel,
stringMessages, raceTimesInfoProvider, parsedPerspectiveOwnSettings.isCanReplayDuringLiveRaces(),
showChartMarkEditMediaButtonsAndVideo, selectedRaceIdentifier,
parsedPerspectiveOwnSettings.getInitialDurationAfterRaceStartInReplay(), raceDTO, asyncActionsExecutor);
parsedPerspectiveOwnSettings.getInitialDurationAfterRaceStartInReplay(), raceDTO, asyncActionsExecutor, raceMap.getTimeRangeActionsExecutor());
racetimePanel.updateSettings(raceTimePanelSettings);
timeRangeWithZoomModel.addTimeZoomChangeListener(racetimePanel);
raceTimesInfoProvider.addRaceTimesInfoProviderListener(racetimePanel);
@@ -307,7 +307,7 @@ public class SimulatorMainPanel extends SimplePanel {
* isScreenLargeEnoughToOfferChartSupport: no wind or competitor chart is shown; use full horizontal
* extension of time panel
*/ false, userService, /*TODO: raceDTO is needed for permission check */null,
/* pending server operations count supplier */ null, timeRangeActionsExecutor);
/* pending server operations count supplier */ null, /* timeRangeActionsExecutor */ null);
busyIndicator = new SimpleBusyIndicator(false, 0.8f);
simulatorMap = new SimulatorMap(simulatorSvc, stringMessages, errorReporter, xRes, yRes, border, streamletPars,
timer, timePanel, windParams, busyIndicator, mode, this, showMapControls,
@@ -49,6 +49,10 @@ import com.sap.sse.common.Util.Pair;
* @author Tim Hessenmüller (D062243)
*/
public class TimeRangeActionsExecutor<Result, SubResult, Key> {
public static interface Listener {
void onNumberOfPendingCallsChanged(int newNumberOfPendingCalls);
}
/**
* Callback called by {@link TimeRangeActionsExecutor#executor} upon receiving an answer from the server for a
* potentially trimmed request. The compound {@code Result} is {@link TimeRangeAsyncCallback#unzipResult(Object)
@@ -80,6 +84,8 @@ public class TimeRangeActionsExecutor<Result, SubResult, Key> {
final TimeRangeResultCache<SubResult> cache = getSubResultCache(key);
cache.registerResult(action, trimmedSubResultForKey);
}
numberOfPendingActions--;
notifyListeners();
}
@Override
@@ -89,6 +95,8 @@ public class TimeRangeActionsExecutor<Result, SubResult, Key> {
callback.onFailure(caught);
callbackWasCalled = true;
}
numberOfPendingActions--;
notifyListeners();
}
/**
@@ -141,9 +149,14 @@ public class TimeRangeActionsExecutor<Result, SubResult, Key> {
}
}
private final Map<Key, TimeRangeResultCache<SubResult>> cacheMap = new HashMap<>(); //TODO Invalidation
private final Map<Key, TimeRangeResultCache<SubResult>> cacheMap = new HashMap<>();
private int numberOfPendingActions;
private final Set<Listener> listeners;
public TimeRangeActionsExecutor() {
this.listeners = new HashSet<>();
}
/**
@@ -202,10 +215,24 @@ public class TimeRangeActionsExecutor<Result, SubResult, Key> {
trimmedTimeRanges.put(subRequest.getKey(), potentiallyTrimmedTimeRange);
}
}
numberOfPendingActions++;
notifyListeners();
action.execute(trimmedTimeRanges, execCallback);
}
private TimeRangeResultCache<SubResult> getSubResultCache(Key key) {
return cacheMap.computeIfAbsent(key, k->new TimeRangeResultCache<>());
}
public void addListener(Listener listener) {
listeners.add(listener);
}
public void removeListener(Listener listener) {
listeners.remove(listener);
}
private void notifyListeners() {
listeners.forEach(l->l.onNumberOfPendingCallsChanged(numberOfPendingActions));
}
}