Skip to content

Invalidate the fastest lap cache when laps of a session change - #490

Merged
LarsLaskowski merged 2 commits into
mainfrom
claude/issue-199-mqne1c
Jul 25, 2026
Merged

Invalidate the fastest lap cache when laps of a session change#490
LarsLaskowski merged 2 commits into
mainfrom
claude/issue-199-mqne1c

Conversation

@LarsLaskowski

@LarsLaskowski LarsLaskowski commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Summary

FastestLapPerSessionCache calculated the entry of a session only once and kept it for the rest of the process lifetime — a session entry was recomputed only when the key was missing. For running sessions new laps were stored but the cached fastest lap was never updated, so the API kept returning the state of the moment the entry was calculated.

The cache now exposes InvalidateSession(sessionId), which drops the cached entry so the next request recalculates it, and RemoveSession(sessionId), which additionally removes the calculation gate of a deleted session. A change counter per session id is incremented on every invalidation; a calculation that started before an invalidation compares the counter before storing its result and discards it when the session changed in the meantime.

The invalidation is triggered wherever completed laps of a session are written or removed:

  • ParticipantRuntimeData.CompleteLap — a completed lap can be the new fastest lap
  • SessionHistoryProcessor.UpdateFinishedLap / RefreshStoredLap / InsertLap — history packets change or add completed laps
  • FinalClassificationProcessor — invalid laps of the session are deleted
  • SessionProcessor.ClearPreviousSessionData — laps of a reused session id are deleted
  • PacketProcessor.RemoveInvalidSessionFromDatabase and SessionsController session deletion — the whole session is gone

FastestLapPerSessionCache had to become public so the packet processing in F1Server.Service can signal the change.

Linked issues

Closes #199

Review notes

  • Laps that are still unfinished (ParticipantRuntimeData.AddLap / RemoveLap) do not trigger an invalidation. Those rows are stored with IsCompleted = false and are excluded by the DbIsCompleted == 1 filter of the calculation, so they can never influence the fastest lap of a session.
  • Invalidation is lazy: the entry is dropped and recalculated on the next request instead of being recomputed eagerly, so a burst of laps during a live session does not cause repeated calculations.
  • RemoveSession removes the SemaphoreSlim of the session without disposing it, so a calculation that is still holding it is not hit by an ObjectDisposedException.
  • Three new tests in FastestLapPerSessionCacheTests cover the new behaviour; the existing test setup was refactored to share an AddSession helper.

claude added 2 commits July 25, 2026 15:50
The per session fastest lap cache calculated an entry only once and kept it
until the process ended, so a running session reported the fastest lap of the
moment its entry was calculated. The cache now offers InvalidateSession and
RemoveSession, and the lap processing drops the affected entry whenever a lap
is completed, refreshed, inserted or removed, and when a session is deleted.
A change counter per session makes sure a calculation that was invalidated
while it was running does not store its outdated result.
…ssor

The new invalidation calls were not covered by tests, so the quality gate
rejected the coverage of the changed lines. Two tests now drive a session
history packet that inserts a lap and one that refreshes an already stored
lap, and verify that the reported fastest lap of the session follows. The
session removal keeps the id of the runtime session instead of a local copy,
so the untested method does not add further uncovered lines.
@sonarqubecloud

Copy link
Copy Markdown

@LarsLaskowski
LarsLaskowski merged commit 7d6b6c7 into main Jul 25, 2026
6 checks passed
@LarsLaskowski
LarsLaskowski deleted the claude/issue-199-mqne1c branch July 25, 2026 16:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

F-280 · No cache invalidation: after a one-time initialization (_cacheInitialized), a session entry is (re)computed …

2 participants