Summary
SemanticRouter.delete() drops the router's search index but never removes the JSON config key the router persists at {name}:route_config. That key is leaked into Redis for every router that is deleted — affecting both real users and the test suite.
This was split out of the test-isolation hardening work (#546) because it requires a product-code change and is logically distinct from the test-only naming/cleanup fixes.
Root cause
- The config key is written on init and on route changes:
redisvl/extensions/router/semantic.py:116 — self._index.client.json().set(f"{self.name}:route_config", ".", self.to_dict())
redisvl/extensions/router/semantic.py:881 — same write on route mutation
delete() only drops the index, not the config key:
redisvl/extensions/router/semantic.py:579 — def delete(self): self._index.delete(drop=True)
clear() similarly only clears indexed docs.
So after delete(), {name}:route_config remains in Redis.
Impact
- Product: Any user calling
router.delete() leaves a stranded :route_config key. A later SemanticRouter.from_existing(name) (semantic.py:154) could read stale config from a router that was supposedly deleted.
- Tests: Confirmed orphaned keys in:
- The
semantic_router fixture in tests/integration/test_semantic_router.py (clear() + delete(), config key survives).
tests/integration/test_key_separator_handling.py — test_semantic_router_uses_index_separator (test_router_sep), test_router_respects_modified_key_separator (router_sep_test), test_router_with_prefix_ending_in_separator (router_trailing_test) create routers with fixed names and never clean up; the index can be dropped but the config key persists.
Proposed change
- Make
SemanticRouter.delete() (and the async equivalent if present) also remove {self.name}:route_config, so deletion fully removes router state.
- Update the affected tests to rely on that (and/or wrap their router creation in try/finally), converting the fixed router names in
test_key_separator_handling.py to per-test names via the redis_test_name fixture.
Acceptance criteria
- After
router.delete(), no {name}:route_config key remains in Redis.
SemanticRouter.from_existing() on a deleted router name fails/returns nothing rather than reading stale config.
- Router-related integration tests leave no
:route_config keys behind after teardown.
Summary
SemanticRouter.delete()drops the router's search index but never removes the JSON config key the router persists at{name}:route_config. That key is leaked into Redis for every router that is deleted — affecting both real users and the test suite.This was split out of the test-isolation hardening work (#546) because it requires a product-code change and is logically distinct from the test-only naming/cleanup fixes.
Root cause
redisvl/extensions/router/semantic.py:116—self._index.client.json().set(f"{self.name}:route_config", ".", self.to_dict())redisvl/extensions/router/semantic.py:881— same write on route mutationdelete()only drops the index, not the config key:redisvl/extensions/router/semantic.py:579—def delete(self): self._index.delete(drop=True)clear()similarly only clears indexed docs.So after
delete(),{name}:route_configremains in Redis.Impact
router.delete()leaves a stranded:route_configkey. A laterSemanticRouter.from_existing(name)(semantic.py:154) could read stale config from a router that was supposedly deleted.semantic_routerfixture intests/integration/test_semantic_router.py(clear() + delete(), config key survives).tests/integration/test_key_separator_handling.py—test_semantic_router_uses_index_separator(test_router_sep),test_router_respects_modified_key_separator(router_sep_test),test_router_with_prefix_ending_in_separator(router_trailing_test) create routers with fixed names and never clean up; the index can be dropped but the config key persists.Proposed change
SemanticRouter.delete()(and the async equivalent if present) also remove{self.name}:route_config, so deletion fully removes router state.test_key_separator_handling.pyto per-test names via theredis_test_namefixture.Acceptance criteria
router.delete(), no{name}:route_configkey remains in Redis.SemanticRouter.from_existing()on a deleted router name fails/returns nothing rather than reading stale config.:route_configkeys behind after teardown.