Keep ModelManager lock generations and fixed-size cache bookkeeping consistent - #2821
Open
voropaevv wants to merge 1 commit into
Open
Conversation
Keep lifecycle entries reserved for holders, waiters, timeout callers, and exception paths until the exact generation is unused. Revalidate decorator warm paths and keep fixed-size cache bookkeeping consistent across aliases, rollback, and reload operations.
voropaevv
marked this pull request as ready for review
August 19, 2026 10:35
voropaevv
requested review from
PawelPeczek-Roboflow,
dkosowski87,
grzegorz-roboflow,
hansent,
probicheaux,
rafel-roboflow and
yeldarby
as code owners
August 19, 2026 10:35
Collaborator
|
Hi there, |
Collaborator
|
Hi there |
Collaborator
|
Hi there, Thanks for the contribution. I've taken a look and looks like the problem you pointed is existing and the resolution may be correct - however, this is quite fundamental piece of the server which I would prefer not to introduce big changes for two reasons:
That's not ideal state - I know. When I have a moment in the following weeks I will come back and reflect on the decision, but we are not merging it to todays release. |
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.
Why
ModelManagercould remove a per-model lock entry while the same lockgeneration was still held or referenced by waiting callers.
A subsequent
add_model()for the same resolved model identifier could thencreate a new generation. A caller waiting on the old lock and a newcomer using
the new lock could initialize the same model concurrently.
The same mutation lifecycle exposed related consistency problems in manager
decorators:
remove/add order;
underlying manager but absent from the LRU queue;
did not complete;
failed eviction candidate from the queue.
Fixes #2819.
What changed
entry.
decision under the stable per-model lifecycle lock.
and cache bookkeeping.
add/remove attempts.
original relative order.
eviction failure.
resolved identifier.
synchronization points rather than scheduling sleeps.
Public method signatures and configured per-model lock-acquisition timeout
values are unchanged. The shared lifecycle-entry guard is not held while
waiting for a per-model lock, constructing a model, or clearing model
resources.
This change addresses the demonstrated process-local load/remove/reload races
and fixed-size cache bookkeeping inconsistencies within one
ModelManagerinstance. It does not introduce active inference-use leases or cross-process
coordination.
Verification
The parent behavior was verified from:
aa9306bd8e3c674c3c0a324635307b7272eb54efParent regression proof
The original lock-generation regression failed on the unchanged parent:
It observed two live lock generations and two concurrent constructors for the
same resolved model identifier.
The expanded mutation regression selection produced:
It reproduced:
The additional exact-order rollback tests all failed on the unchanged parent:
The tests cover:
test_fixed_size_cache_failed_direct_remove_preserves_exact_lru_ordertest_fixed_size_cache_failed_eviction_restores_skipped_pinned_ordertest_fixed_size_cache_failed_multi_eviction_keeps_only_registered_modelsCandidate
The expanded mutation regression selection passed:
The additional exact-order rollback selection passed:
Targeted manager tests:
Manager and cache suites:
Full applicable CPU unit suite with a fresh model cache:
The same three failures reproduce on the unchanged parent:
test_factory_logs_construction_failures_before_falling_backtest_cached_model_aggregation_excludes_conflicting_metadatatest_index_list_parameters_by_frame_id_warns_once_per_keyThey are existing logging-capture failures where the warning is emitted but is
not available through
caplog.Incomplete implementations rejected
The regression coverage rejects intentionally incomplete alternatives:
Quality gates
Passed:
git diff --checkThe informational Flake8 pass still reports the existing upstream warning set.
Not verified
non-mutation access paths.
max_sizeguarantee during simultaneous cold loads ofdifferent identifiers.
Risks / rollback
The lifecycle-entry guard briefly serializes entry reservation and retirement,
but it is never held during per-model lock waiting, model construction, or
resource cleanup.
Post-mutation queue reconciliation uses a blocking
_queue_lockacquisition soa secondary bookkeeping timeout cannot replace the original add/remove result
or exception. It can therefore wait behind an ongoing eviction.
The existing eviction path already holds
_queue_lockwhile removing anevicted model and running
clear_cache(). This patch does not acquire_queue_lockwhile holding a per-model lifecycle lock, so it does notintroduce the opposite lock order. Reducing the existing eviction critical
section is outside this change.
Different resolved model identifiers continue to use independent per-model
locks.
Reverting this PR restores the previous mutation and cache-bookkeeping
behavior.
Migrations / external effects
No migrations or public API changes.
A warm
add_model()call that overlaps an already-started removal may now waitfor that removal to complete instead of returning from an unlocked decorator
fast path. Configured per-lock acquisition timeout values are unchanged, although this path may perform two sequential lock acquisitions.
Screenshots / preview
Not applicable.