Files
sailing-analytics/java/com.sap.sailing.server
Axel Uhl 24ec9cb3f0 bug6241: reschedule wind-estimation install when polar service arrives
Closes a replica-bootstrap ordering hazard uncovered by working through
the replication path in detail:

On a replica, RacingEventServiceImpl.initiallyFillFromInternal
deserializes each DynamicTrackedRegatta with its trackedRaces map
already populated (the map is non-transient in TrackedRegattaImpl), so
no raceAdded events fire during deserialization itself. What fires
raceAdded on the replica is the subsequent
ensureRegattaHasRaceAdditionListener call, which invokes
TrackedRegatta.addRaceListener(...) -- and that method synchronously
replays raceAdded(...) for every pre-existing tracked race (see the
addRaceListener body in TrackedRegattaImpl and its Javadoc: 'firing
events for the already existing TrackedRace instances when adding a
new listener').

At that moment, both polarDataService and windEstimationFactoryService
in the replica's RacingEventServiceImpl may still be null (their OSGi
trackers have not fired yet -- their arrival order is undetermined).
Two scenarios need handling:

 * Polar service arrives first, factory second: raceAdded skipped the
   scheduleWindEstimationInstallation call because the factory was
   null; setWindEstimationFactoryService then iterates all races and
   schedules installs, which observe a non-null polar service and
   proceed as intended. This case already worked.

 * Factory arrives first, polar service second: raceAdded skipped the
   trackedRace.setPolarDataService call because the polar service was
   null; setWindEstimationFactoryService then schedules an install per
   race. The install's runWhenPastLoading callback fires immediately
   because replicated races typically arrive already past LOADING; it
   sees polarDataService == null and silently drops out, never
   registering a runWhenPolarLoadingFinishedFor callback. Then
   setPolarDataService iterates via setPolarDataServiceOnAllTrackedRaces
   and attaches the polar service to each race -- but nothing was
   retriggering the wind-estimation install. This case was BROKEN.

Fix: in setPolarDataServiceOnAllTrackedRaces, capture the wind factory
at method entry and, if it's already available when the polar service
arrives, reschedule the install per race.
scheduleWindEstimationInstallation is idempotent and guarded against
duplicate installation, so this is a safe no-op for races that already
got their estimator through another code path.

Notes on the broader replication picture (informing this fix):

 * TrackedRaceImpl.polarDataService and .windEstimation are both
   transient; after deserialization on the replica they are null and
   must be set explicitly by the RaceAdditionListener path.

 * PolarDataService has no PolarDataOperation implementations and
   PolarDataServiceImpl never calls replicate(...); the primary's
   polar model state is shipped once via
   serializeForInitialReplicationInternal /
   initiallyFillFromInternal (which replaces the polarDataMiner
   wholesale on the replica), and after that the replica re-mines
   independently from fixes fed through its own PolarFixCacheUpdater
   (installed by raceAdded).

 * TrackedRaceReplicatorAndNotifier.windDataReceived explicitly
   filters out WindSourceType.MANEUVER_BASED_ESTIMATION when
   replicating wind fixes (see the existing check), so replicas run
   their own estimator locally and produce their own fixes -- which
   makes correct estimator installation on the replica just as
   important as on the primary.
2026-07-14 18:33:30 +02:00
..
…