Repository navigation
OP#10282: Parse track files off the event loop - #840
Merged
randy-seng merged 5 commits intoSep 29, 2026
Merged
randy-seng merged 5 commits into
randy-seng merged 5 commits into
Conversation
randy-seng
force-pushed
the
task/10282-keep-the-web-ui-responsive-while-loading-track-files
branch
from
September 9, 2026 22:01
a60313d to
8f2dd1e
Compare
randy-seng
force-pushed
the
task/10282-keep-the-web-ui-responsive-while-loading-track-files
branch
from
September 9, 2026 22:22
8f2dd1e to
cacd6ee
Compare
randy-seng
force-pushed
the
task/10282-keep-the-web-ui-responsive-while-loading-track-files
branch
2 times, most recently
from
September 14, 2026 16:33
5426fd9 to
8cfad37
Compare
randy-seng
force-pushed
the
task/10282-keep-the-web-ui-responsive-while-loading-track-files
branch
from
September 16, 2026 11:42
83d6c56 to
4a3a68c
Compare
randy-seng
force-pushed
the
task/10282-keep-the-web-ui-responsive-while-loading-track-files
branch
from
September 16, 2026 14:06
4a3a68c to
7e4ece5
Compare
randy-seng
force-pushed
the
task/10282-keep-the-web-ui-responsive-while-loading-track-files
branch
from
September 16, 2026 16:34
7e4ece5 to
34e9e5d
Compare
schubsen
previously requested changes
Sep 21, 2026
Base automatically changed from
task/10281-show-progress-of-long-operations-in-the-web-ui
to
main
September 21, 2026 12:46
Parsing moved off the event loop, so the click that starts loading returns long before the tracks are in the repository. Nothing in the browser said so: no progressbar, no disabled buttons, nothing. A user opening a large otconfig saw an idle looking application with live buttons that silently did nothing, and the acceptance tests, which slept a fixed five seconds and then carried on, clicked "Export track statistics ..." into an application without tracks. LoadTrackFiles already took a ProgressbarBuilder but never used it. Work handed to a worker thread cannot be tracked by decorating a sequence, so builders now also start a progressbar the caller closes again. Builders that can only decorate a sequence show nothing, which is what a command line run wants. The acceptance helpers wait for that progressbar to disappear instead of sleeping. While there, poll for the exported file rather than sleeping five seconds and asserting it exists: exporting takes about four seconds here, so the wait was already marginal and failed on a busy machine.
LoadTrackFiles used __call__ for the blocking load and load for the awaitable one, while LoadOtconfig next to it used load and load_async. That made load mean the opposite thing in two neighbouring use cases. LoadTrackFiles now follows LoadOtconfig: load blocks, load_async parses off the event loop, and __call__ delegates to load so PreloadInputFiles keeps working.
…ge across test cases
randy-seng
force-pushed
the
task/10282-keep-the-web-ui-responsive-while-loading-track-files
branch
from
September 21, 2026 12:46
34e9e5d to
3c4a720
Compare
briemla
self-requested a review
September 28, 2026 18:22
briemla
approved these changes
Sep 28, 2026
briemla
dismissed
schubsen’s stale review
September 28, 2026 18:24
The requested change has been implemented. A review by another person has been done.
randy-seng
deleted the
task/10282-keep-the-web-ui-responsive-while-loading-track-files
branch
September 29, 2026 09:08
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Opening an otconfig or adding track files parsed everything on the event loop, so the browser froze for as long as parsing took — on a large project, minutes with no repaint and no way to tell whether anything was happening.
LoadTrackFiles.load_asyncnow handsTrackParser.parse_filestoasyncio.to_threadand publishes the result back on the event loop, and it opens a progressbar for the duration so the user can see the application is busy.LoadOtconfiggained a matchingload_async, andDummyViewModel.load_tracks/_load_otconfigawaitit.
Why
Parsing is the expensive part and it is pure — no repository, no observer, no widget — so it is the only part safe to move off the loop.
Everything downstream of it notifies observers that mutate widgets, so
_publishstays on the loop. That split is why the use case grew a_parse/_publishpair rather than just wrapping the old__call__in a thread.The blocking path could not simply be deleted:
PreloadInputFilesloads a--configfile at startup, before any loop exists. So both paths stay, andloadnow raises if it finds a running loop rather than freezing the ui for a caller who picked the wrong one.ProgressbarBuilderonly knew how to decorate a sequence, which cannot track work done on another thread. It gainedstart(...) -> RunningProgressbar, a handle the caller closes; the default implementation returnsNoRunningProgressbar, so command line runs show nothing — their output is already a log.Notes for the reviewer
Start at
OTAnalytics/application/use_cases/load_track_files.py— theload/load_asyncpair and the_parse/_publishsplit are the whole change. The docstring onload_asyncstates the invariant the rest depends on.load_otconfig.pylooks like a big diff but is mostly extraction: the oldloadbody became_begin/_publish_before_tracks/_publish_after_tracks/_abort, shared by a sync and an async_apply. The behaviour is unchanged;test_publishes_everything_the_blocking_load_publishespins that.Naming: the last commit renamed
LoadTrackFiles.__call__semantics to matchLoadOtconfig—loadblocks,load_asyncyields,__call__delegates toload.loadmeant opposite things in the two neighbouring use cases before.The acceptance helper change is the other half of the fix:
open_project_otconfigandadd_track_via_pickerslept a fixed 5s and carried on, which after this change means clicking into an application that has no tracks yet. They now wait for the parsing progressbar to disappear (wait_for_track_loading_to_finish), treating "never appeared within 5s" as "nothing to parse".Risk and rollout
Anything calling
add_tracks_of_filesorload_otconfigfrom inside a running loop now raisesRuntimeErrorinstead of silently freezing. That is deliberate and loud, but it is a behaviour change for any call site not updated here — the switch isadd_tracks_of_files_async/load_otconfig_async. The desktop and CLI paths still use the blocking ones.Failure mode to watch for: a progressbar that never closes.
close()sits in afinally, so a parser exception still clears it;test_closes_the_progressbar_when_parsing_failscovers that case.Revert is the four commits — nothing persisted, nothing migrated.
Testing
Still to verify by hand: the acceptance suite (
tests/acceptance) — the newwait_for_track_loading_to_finishand the export file polling werenot exercised here, and the 120s timeouts were chosen from local timings rather than measured on CI.
OP#10282