Issue #506: feat: Make logout summarization non-blocking - #1154
Issue #506: feat: Make logout summarization non-blocking#1154dereck-symmetry wants to merge 1 commit into
Conversation
bjagg
left a comment
There was a problem hiding this comment.
Overview
Makes /logout return immediately by moving interaction summarization into a background task, fixing #506 ("kick off background task"). Small and focused, and the error handling is right: _safe_summarize catches broadly but uses logger.exception rather than a bare pass, so failures are still visible. test_logout_succeeds_even_when_summarization_fails is exactly the test I'd want here — it proves the user-facing path is genuinely decoupled from LLM availability.
Two things I'd like changed before merge, and a couple of notes.
1. The task reference is discarded
asyncio.create_task(_safe_summarize(agent, task, username))The return value isn't kept. The event loop holds only a weak reference to a running task, so this can be garbage-collected mid-execution — the CPython docs call this out directly and recommend saving a reference. The failure mode is nasty precisely because it's rare and load-dependent: summaries silently vanish some fraction of the time, with nothing in the logs.
Minimal fix:
_background_tasks: set[asyncio.Task] = set()
task_ref = asyncio.create_task(_safe_summarize(agent, task, username))
_background_tasks.add(task_ref)
task_ref.add_done_callback(_background_tasks.discard)2. FastAPI's BackgroundTasks is the better fit here
FastAPI has a first-class mechanism for "do this after the response is sent":
async def logout(background_tasks: BackgroundTasks, username: str = Depends(get_current_user)):
...
background_tasks.add_task(_safe_summarize, agent, task, username)It solves the reference problem for you, and — the part I care more about — it makes the tests deterministic. TestClient runs background tasks to completion before returning, so the two await asyncio.sleep(0.1) calls disappear.
Those sleeps are the second thing I'd change. A fixed 100ms as a synchronization barrier is timing-dependent and will flake under CI load; grep says these would be the only such sleeps in the whole test suite. If BackgroundTasks isn't wanted for some reason, the alternative is to capture the task and await it in the test rather than sleeping.
Worth noting the repo doesn't use BackgroundTasks anywhere yet, so either way this establishes a pattern — which is an argument for establishing the framework-idiomatic one.
3. Nothing survives shutdown — and this weakens #1118
bases/lif/advisor_restapi/core.py has no on_event("shutdown") or lifespan handler. When an ECS task stops (a deploy, a scale-in, a health-check failure), any in-flight summarization is killed and the interaction summary is lost with no trace beyond an absent log line.
That matters because #1118 already tracks interaction-summary capture being best-effort and logout-only. This change makes the window wider: previously the summary completed before the response returned, so a user who logged out successfully had their summary saved. Now a successful logout no longer implies that.
Not asking you to solve durability here — that's #1118's job. But it's worth a line in the PR description or a Refs #1118, because this trades a latency win for a durability loss and that trade should be visible rather than discovered later.
4. The TODO(#986) marker was dropped
The prompt string moved into _safe_summarize, but the comment went with it:
# TODO(#986): move this hard-coded query prompt to env/config#986 is still open. That comment was its only in-code anchor — worth carrying it over to the new location.
Verdict
Approve once items 1 and 2 are addressed — the unretained task is a real (if intermittent) correctness issue, and the sleeps will cost someone a flaky-CI investigation. Items 3 and 4 are notes, not blockers.
The core change is right and the failure-path test is a good addition.
Description of Change
These change fix issue #506. We add a asynch io call and return immediately from a logout call.
Closes #506
Type of Change
to not work as expected)
Project Area(s) Affected
Checklist
uv run ruff check)uv run ruff format)uv run ty check)docs/and project README updated
and CHANGELOG.md entry
Testing
Additional Notes
Risks are very low that the logout will not complete. That would only happen if the logout background task is incomplete when there is a server restart.
Testing and code checks done with Claude.