FastGPT serializes requests per chatId server-side; the LangGraph
backend held all state in memory with no locking, so two concurrent
requests on one session could interleave (checkpoint write races,
garbled no_reply/turn bookkeeping).
- AccidentAppService holds per-session asyncio locks; chat(), stream()
and delete_session() execute under the session lock (LLM call
included - same-session turns are strictly serialized, different
sessions never contend)
- set_info/get_info stay synchronous and lock-free: repository
load/apply_update are atomic dict operations with no mixed
intermediate state; a racing set vs chat yields one complete value
- delete pops the lock entry after cleanup; a chat that arrived
concurrently executes afterwards against the fresh (deleted)
session - matching FastGPT's delete-then-chat new-conversation
semantics
- tests: same-session concurrent chats serialize (interval pairing
probe), different sessions run parallel, delete waits for in-flight
chat, chat-vs-set interleave leaves no torn values
Verified: 219 unit tests (4 new concurrency tests)