Repository navigation
[Bug]: Semantic session manager and semantic service each build their own config cache, so set type deletes and registrations do not reach ingestion #1730
Description
Describe the bug
The semantic session manager and the semantic service each get their own CachingSemanticConfigStorage over the same config database. Set type writes go through the session manager's instance, but set configs, which carry the categories a set inherits from its set type, are read and cached through the service's instance. Writes through one instance never invalidate the other. So after a set type is deleted, ingestion keeps extracting with its deleted categories; after a set is registered to a new set type, ingestion does not see that type's categories. Both last until a later write through the service's instance happens to clear its set config cache (a category, tag or category template change), or until the process restarts.
As of 82b6c6f58 (main), paths under packages/server/src/memmachine_server/:
common/resource_manager/semantic_manager.py:175-194:get_semantic_config_storagebuilds a newSemanticConfigStorageSqlAlchemy, wrapped in a newCachingSemanticConfigStoragewhenwith_config_cacheis set (the default,common/configuration/__init__.py:154-157), on every call. It is called once for the service (:242) and again for the session manager (:268).semantic_memory/config_store/caching_semantic_config_storage.py:20-25states that "Cache entries are invalidated on write operations"; each write invalidates only its own instance's dictionaries (for exampledelete_set_type_id,:336-346, andregister_set_id_set_type,:97-117).- The session manager writes set types through its instance:
add_set_type_id(semantic_memory/semantic_session_manager.py:484,:503),delete_set_type_id(:516),register_set_id_set_type(:388,:646). - The service reads set configs through the other instance:
_set_id_resource(semantic_memory/semantic_memory.py:505), which supplies ingestion's categories andget_set_id_category_names, and_set_ids_embedders(:476). A set config includes the categories inherited from the set's registered set type (semantic_memory/config_store/config_store_sqlalchemy.py:317-337).
Steps to reproduce
Build the real SemanticResourceManager (SQLite config and feature databases, mock embedder and language model) and call the public session manager methods behind /memories/semantic/set_type, /memories/semantic/set_type/delete and /memories/semantic/category/template:
session_manager = await manager.get_semantic_session_manager()
service = await manager.get_semantic_service()
type_1 = await session_manager.create_set_type(session_data=session, metadata_tags=["topic"])
await session_manager.add_category_template(set_type_id=type_1, category_name="travel_plans", prompt="p", description=None)
set_id = await session_manager.get_set_id(session_data=session, set_metadata_keys=["topic"], set_metadata={"topic": "x"})
await session_manager.delete_set_type(set_type_id=type_1)
type_2 = await session_manager.create_set_type(session_data=session, metadata_tags=["topic"])
await session_manager.add_category_template(set_type_id=type_2, category_name="budget", prompt="p", description=None)
await session_manager.get_set_id_category_names(set_id=set_id) # any read, e.g. an ingestion pass
await session_manager.get_set_id(session_data=session, set_metadata_keys=["topic"], set_metadata={"topic": "x"})Measured, comparing get_set_id_category_names (served) with an uncached SemanticConfigStorageSqlAlchemy read of the same set (stored):
service and session manager share one config store: False
before delete (served, stored): (['travel_plans'], ['travel_plans'])
after delete (served, stored): (['travel_plans'], [])
after re-register (served, stored): ([], ['budget'])
Not run: a full server with background ingestion. Ingestion reads the same _set_id_resource on every pass (semantic_memory/semantic_ingestion.py:123).
Expected behavior
One process has one semantic config cache. SemanticResourceManager builds the config storage once and gives the same instance to the service and the session manager, so every write invalidates the cache that serves later reads, and a set's categories reflect its current set type.
Environment
- MemMachine:
mainat82b6c6f58 - Python 3.14.3, SQLite 3.50.4, macOS
semantic_memory.with_config_cache: true(the default)
🤖 Written by Claude Code (Claude Opus 5.5) on behalf of @edwinyyyu.
Activity