mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-21 13:50:20 +08:00
CI (integration shard 1) hit the uninstall-resurrect again: after
uninstall_repository, GET /api/tools/{guid} still returned the tool. The
log shows the interleaving - the reload_toolbox queued by the preceding
install's conf write executed while the uninstall was mid-flight, and its
rebuild (including a potentially long inline index populate) ran with no
synchronization against remove_tool_by_id.
Two halves:
1. _get_new_toolbox now builds and swaps the new toolbox under
app._toolbox_lock, the lock remove_tool_by_id and
invalidate_index_cache already hold. Whichever side wins, the other
sees a consistent world: removal-first means the rebuild reads the
already-cleaned index and conf; rebuild-first means the removal runs
against the swapped-in box. The lock is an RLock, so the populate
broadcast delivered inline on the same thread re-enters safely.
2. remove_tool_by_id also cleans the CURRENT app.toolbox when it is a
different object than self - a rebuild that won the race swapped in a
box built from the pre-removal index, and cleaning the superseded
instance alone would leave the live box serving the uninstalled tool.
Verified: new unit test (swapped-in box cleaned), 45 lazy unit tests,
fastp shed-install + repository-uninstall integration tests in lazy mode
(the lock's deadlock canary - install triggers watcher reload + inline
populate under the lock), tox lint/format/mypy.