From 1a42d09e35469ffcd9b7d1215d6c840c678ad029 Mon Sep 17 00:00:00 2001 From: Jerome Lacoste Date: Fri, 13 Mar 2026 11:39:55 +0100 Subject: [PATCH] fix: avoid race condition in retro controller analysis loading Register the lastAnalysisEvent listener before calling requestAnalysis to prevent missing events that arrive between the request and listener registration. Also check if analysis already completed before waiting. Fixes #2750 --- lib/src/model/analysis/retro_controller.dart | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/src/model/analysis/retro_controller.dart b/lib/src/model/analysis/retro_controller.dart index 7e2096c042..ca703cde93 100644 --- a/lib/src/model/analysis/retro_controller.dart +++ b/lib/src/model/analysis/retro_controller.dart @@ -113,8 +113,24 @@ class RetroController extends AsyncNotifier with EngineEvaluationMix _root = _game.makeTree(); if (_game.serverAnalysis == null) { + // Add listener before requesting analysis to avoid missing events + // that arrive between the request and listener registration. + serverAnalysisService.lastAnalysisEvent.addListener(_listenToServerAnalysisEvents); + await serverAnalysisService.requestAnalysis(options.id); + // Check if analysis already completed (e.g. was requested from the + // analysis screen and finished before we started listening). + final existingEvent = serverAnalysisService.lastAnalysisEvent.value; + if (existingEvent != null && + existingEvent.$1 == options.id && + existingEvent.$2.isAnalysisComplete) { + ServerAnalysisService.mergeOngoingAnalysis(_root, existingEvent.$2.tree); + state = AsyncData(await _computeMistakes(options.initialSide)); + requestEval(); + return state.requireValue; + } + _serverAnalysisCompleter.future.timeout( kMaxWaitForServerAnalysis, onTimeout: () { @@ -148,8 +164,6 @@ class RetroController extends AsyncNotifier with EngineEvaluationMix state = AsyncValue.data(retroState); - serverAnalysisService.lastAnalysisEvent.addListener(_listenToServerAnalysisEvents); - return retroState; }