fix(router): make delete_deployment wildcard cleanup symmetric with upsert

After the previous commit moved _remove_deployment_from_wildcard_state out
of the inner index-map guard in upsert_deployment, delete_deployment was
still calling it only inside `if deployment_idx is not None`. Greptile
flagged the asymmetry: under a desynced index_map, delete would silently
leave the stale wildcard credential in pattern_router.

Moves the cleanup call to the top of the try block, mirroring the upsert
path. Cleanup is idempotent so the change is a no-op on the happy path.
Adds a regression test that simulates the desync by removing the entry
from model_id_to_deployment_index_map and asserts delete still clears
pattern_router.
This commit is contained in:
Aarkin7 2026-06-04 22:05:15 +05:30
parent 0f241a28c4
commit 988f73ef6e
2 changed files with 24 additions and 1 deletions

View file

@ -8715,6 +8715,9 @@ class Router:
deployment_idx = self.model_id_to_deployment_index_map[id]
try:
# Idempotent and symmetric with upsert_deployment, so a desynced
# index_map cannot leave stale wildcard credentials behind.
self._remove_deployment_from_wildcard_state(model_id=id)
if deployment_idx is not None:
# Pop the item from the list first
item = self.model_list.pop(deployment_idx)
@ -8723,7 +8726,6 @@ class Router:
self._update_deployment_indices_after_removal(
model_id=id, removal_idx=deployment_idx
)
self._remove_deployment_from_wildcard_state(model_id=id)
_budget_limiter = self._get_router_deployment_budget_limiter()
if _budget_limiter is not None:
_budget_limiter.unregister_deployment_budget(model_id=id)

View file

@ -4448,3 +4448,24 @@ def test_remove_deployment_from_wildcard_state_is_noop_for_empty_id():
assert router.pattern_router.patterns == snapshot_patterns
assert router.provider_default_deployment_ids == snapshot_ids
def test_delete_deployment_cleans_wildcard_state_even_when_index_is_desynced():
"""
Symmetric with the upsert path: delete_deployment must clean wildcard
state from the model_id regardless of whether the fast-mapping index
still knows about it. Simulates index corruption / partial-failure by
removing the entry from model_id_to_deployment_index_map while leaving
pattern_router intact, then calls delete and asserts pattern_router is
cleaned.
"""
router, _ = _build_wildcard_router(api_key="key-A")
model_id = "wildcard-deployment-1"
assert router.pattern_router.patterns
del router.model_id_to_deployment_index_map[model_id]
router.delete_deployment(id=model_id)
assert router.pattern_router.patterns == {}
assert model_id not in router.provider_default_deployment_ids