Skip to content

fix(app): refetch the Home session index on window focus - #55301

Open
shreyanshj10 wants to merge 2 commits into
anomalyco:devfrom
shreyanshj10:session-list-refresh
Open

shreyanshj10 wants to merge 2 commits into
anomalyco:devfrom
shreyanshj10:session-list-refresh

Conversation

@shreyanshj10

@shreyanshj10 shreyanshj10 commented Oct 14, 2026 •

Copy link
Copy Markdown

Issue for this PR

Fixes #55098

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

app.tsx turns refetchOnMount, refetchOnReconnect and refetchOnWindowFocus off for every
query. home-sessions opts back into mount and reconnect but not focus, and
["home-sessions", conn] is only ever invalidated by Home's own rename and delete paths. So
nothing refreshes the list except a remount or a reconnect.

That is enough while every session is announced on this client's own stream. It is not enough when
a second opencode serve shares the database: the other process publishes session.created on its
own bus, so the new session is in GET /api/session on both servers while only one stream
announced it, and the client that missed the event needs a restart to see it.

So the query opts back into focus refetching too, and Home re-reads the index when you return to
the window. staleTime stays at 30s and Query only refetches on focus once the data is past it, so
switching straight back costs nothing, nothing runs while the window is away, and the focus manager
owns the visibilitychange listener, so there is no listener to leak and no refetch stacking on one
in flight. The four refetch options sit in home/sessions/refetch.ts and are spread at the single
call site.

Client half only, and only for "I came back and the list is stale": a session created elsewhere
while Home stays in front still waits for the next focus. A cross-process event bus (#45549) is
what would make the list update immediately.

How did you verify your code works?

Ran the new home/sessions/refetch.test.ts case, the typecheck in packages/app, and oxlint on the
changed files. The new case mounts a client with the app-wide defaults, lets the index go stale,
fires visibilitychange and expects exactly one refetch - and none while the data is still fresh.
It fails without the refetchOnWindowFocus opt-in.

For a real second server, the repro script on the issue is the setup - two opencode serve
processes on one data dir, create a session on B, then come back to Home on A. The issue's own
finding is that the session shows up there only after a restart.

Screenshots / recordings

No visual change - the same rows, refreshed when you return to them.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Added by the opencode bot (AI-generated).

Related: #45549, #53146, #51213

@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The one-line fix does what it says. A periodic refetch of GET /api/session would show sessions created by another opencode serve on the same database: I ran the #55098 script from source, and the second server's stream got no session.created while its session list already included the session. I did not run the desktop or web app, so I didn't see the Home list refresh. bun test src/home/sessions (25 pass) and the packages/app typecheck are clean. Public API unchanged.

Main concern: each refetch reloads the whole session history, not one page. loadHomeSessionIndex keeps fetching 5,000 sessions at a time until it reaches the end. With this change, every client on Home does that every 30s, against local and remote servers alike, for a setup (two servers sharing one opencode.db) that maintainers may not consider supported. Refetching on focus/visibility would cover "I switched back and the list is stale" much more cheaply. Otherwise the server-side event fix (#45549) is the better place for this. The added code comment isn't needed for a one-option change and can be dropped.

Related: #45549, #53146, #51213

// A second server on the same database publishes `session.created` on its own process's bus,
// so nothing on this stream ever announces the sessions it creates. Re-read the index on the
// staleness window rather than waiting for a remount or a reconnect to be the only way back.
refetchInterval: 30_000,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each refetch runs loadHomeSessionIndex, which fetches every page of the session history (5,000 per page until the end), not just the newest rows. With refetchInterval: 30_000 every client on Home repeats that every 30s, for every user and every server (including remote ones), to cover the two-servers-on-one-database case. Could this be refetchOnWindowFocus: true (and/or a refetch on visibilitychange) instead, or at least a much longer interval? That would cover returning to the app while costing far less.

The 30s interval had every client on Home walk the whole session history on a timer. Opt the query into focus refetching instead: returning to the window re-reads the index once it is past its stale time, and nothing runs while the window is away.
@shreyanshj10 shreyanshj10 changed the title fix(app): refresh the Home session index on an interval fix(app): refetch the Home session index on window focus Oct 14, 2026
@shreyanshj10

Copy link
Copy Markdown
Author

Thanks, that's a fair objection and I've taken the focus route.

You're right about the cost: loadHomeSessionIndex walks the whole history a page at a time, so
putting it on a 30s timer meant every client on Home paid for a full index walk forever, against
remote servers too, to cover a two-servers-on-one-database setup. That is a bad trade for the case
it buys.

The interval is gone. The query sets refetchOnWindowFocus: true instead, so it re-reads the index
when you come back to the window rather than while you're away. staleTime is still 30s and Query
only refetches on focus once the data is past it, so coming straight back costs nothing, and the
focus manager owns the visibilitychange listener and its teardown, so there is no listener of ours
to leak and no refetch stacking on one in flight (onFocus refetches with cancelRefetch: false).
Worth being precise about the reach: v5 drives focus refetching off visibilitychange alone, so in
the desktop window this fires when the window is hidden, minimised or occluded and comes back, not
on every app switch. The three-line comment is gone as well.

The four refetch options now sit in a small home/sessions/refetch.ts and are spread at the single
call site, so the test can assert the behaviour rather than the literal: it mounts a client carrying
the app-wide defaults, lets the data go stale, fires visibilitychange and expects exactly one
refetch - and none while the data is still fresh. Dropping refetchOnWindowFocus makes it fail. I
kept them out of home/sessions/index.ts on purpose: that file has anti-slop warnings on lines I
have no business touching, and lint:changed would attribute them to this PR. Happy to inline the
options at the call site instead if you'd rather not have the extra file.

#53752 and this don't collide as far as I can see: that one invalidates the index when the stream
comes back after a drop, which never happens in the two-server case because this client's stream
stays up the whole time. Different trigger, same query.

This now covers "I came back and the list is stale" and nothing more; a session created on another
server while Home stays in front still waits for the next focus. The immediate fix is the
cross-process event bus in #45549, and I'm happy for this to close in favour of it if you'd rather
the whole thing live server-side.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

desktop: session list does not update when another server sharing the database creates a session

1 participant