Answer unchanged conversations with 304, pause chat polls while hidden - #17
Merged
Merged
Conversation
Yoonwoo-Ha
force-pushed
the
perf/chat-poll-etag
branch
2 times, most recently
from
September 24, 2026 10:50
50975e5 to
e87cf39
Compare
devswha
requested changes
Sep 24, 2026
devswha
left a comment
Owner
There was a problem hiding this comment.
Thanks. The 304 path and the pause while hidden are good ideas. #18 is now merged, so please rebase onto it. #17 must not land before #18: without #18's chain fingerprint, the ETag doesn't change when the earlier-rollout chain does, so the chat would stay on the old answer. On top of #18 the ETag follows the chain. Beyond the rebase:
- The chat can freeze on an unfilled gap. In
ChatView.tsx~295,lastAnswer.current = conversationis set before the gap fill (await turnsBetween) and beforesetState. Scenario: older pages are shown and the newest page has moved past the held start, so a gap fill is running. The tab goes hidden, and the read is cancelled. Back on screen, the samefrom=request gets a 304 and the same object, so the early return fires. The gap is never filled,heldFromnever moves, and new turns never appear until the file changes, which may be never if the agent has finished. Please setlastAnsweronly at the end of the success path, or clear it when the read is cancelled. beforepages fill the client cache. Pages fetched withbeforeare never requested again, but each takes a slot inconversationAnswers(api.ts~91–110), and a 304 doesn't move the polled entry up. Once 16 slots fill, the newest-page entry is the first to go, which costs a multi-MB reload while the dead pages stay in memory. Please only send and store ETags whenbeforeis not set.
…e hidden The chat polls its conversation every 2s, and a newest page can be megabytes (1.6MB measured on a working agent): on a phone that is data and battery spent on nothing new. - Each conversation answer carries an ETag naming the page asked for, the transcript file's state and the server process. The chat sends it back, and an unchanged conversation answers 304 with no body; the chat then keeps the very answer it shows and skips laying it out again. The PC proxy carries the ETag both ways and passes a 304 on bodyless. - The conversation and prompt polls pause while the page is hidden (another tab, a minimized window, a phone app in the background) and poll at once when it is back, as chatmux does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…led pages only Review follow-ups: - The chat recorded the answer as shown before the gap fill ran. A read cancelled mid-way (the page hidden while the turns between the held start and the newest page were fetched) left it recorded. Back on screen, the same held-start request got a 304 and the same object, so the read returned early: the gap never filled and new turns never appeared. The answer is now recorded only once it is laid out in full. A browser check that hides the page during a slow gap fill froze before this change and fills the gap after it. - Older pages (`before`) are asked for once, so they no longer send or keep an ETag. They used to take the cache's slots and push out the polled newest page, and a 304 did not move that entry up. A 304 now refreshes the polled entry, and only polled pages are kept. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Yoonwoo-Ha
force-pushed
the
perf/chat-poll-etag
branch
from
September 24, 2026 12:14
e87cf39 to
1ca749f
Compare
Contributor
Author
|
Thanks. Rebased onto main with #18 (the ETag now follows the chain's stream id). Addressed in 1ca749f:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The chat polls its conversation every 2s, and each answer can be megabytes: 1.6MB per poll measured on a working agent. On a phone that spends data and battery on polls that bring nothing new.
304with no body. The chat then keeps the answer it already shows and skips comparing and laying it out again.Cache-Control: no-storekeeps the browser's own cache out of the way so the chat sees the 304. The PC proxy carries the ETag both ways and passes a 304 on without a body.Rebased onto main now that #5 is merged: the ETag covers #5's pages (
before/since/from). #6 and #18 touchChatView.tsxandconversation.tsnearby, so whichever merges later needs a small rebase.Measured (live server with #5 applied, polling every 2s for 20s; without #5 a full answer is larger, the 304s are the same 0 bytes)
Testing
bun run typecheckpasses andbun testpasses 271/271 after the rebase.If-None-Matchis sent, and a 304 returns the very same object304/0B🤖 Generated with Claude Code