Summary
MemorySubstrate::save_session() is synchronous and is called directly from the async agent loop. This holds the SQLite connection mutex on a tokio worker thread during disk writes. On low-core deployments, that can starve the runtime and delay unrelated requests such as health checks.
Evidence in current code
crates/librefang-memory/src/substrate.rs exposes only synchronous save_session()
crates/librefang-runtime/src/agent_loop.rs calls memory.save_session(...) from async code in multiple places
- Other memory APIs already use async / blocking-offload patterns, so session persistence is the outlier
Risk
- Single-core or low-concurrency deployments can stall while SQLite writes are happening
- Health endpoints and daemon responsiveness can degrade under load
Proposed fix
- Add
save_session_async() to MemorySubstrate using tokio::task::spawn_blocking
- Switch async agent loop call sites from
save_session() to save_session_async().await
- Keep synchronous
save_session() for purely sync callers
Upstream reference
Similar fix discussed in RightNow-AI/openfang#534.
Summary
MemorySubstrate::save_session()is synchronous and is called directly from the async agent loop. This holds the SQLite connection mutex on a tokio worker thread during disk writes. On low-core deployments, that can starve the runtime and delay unrelated requests such as health checks.Evidence in current code
crates/librefang-memory/src/substrate.rsexposes only synchronoussave_session()crates/librefang-runtime/src/agent_loop.rscallsmemory.save_session(...)from async code in multiple placesRisk
Proposed fix
save_session_async()toMemorySubstrateusingtokio::task::spawn_blockingsave_session()tosave_session_async().awaitsave_session()for purely sync callersUpstream reference
Similar fix discussed in RightNow-AI/openfang#534.