Skip to content

Reconnect the desktop client when the local daemon socket drops - #218

Open
yaffalhakim1 wants to merge 2 commits into
egoist:mainfrom
yaffalhakim1:fix/local-daemon-socket-reconnect
Open

Reconnect the desktop client when the local daemon socket drops#218
yaffalhakim1 wants to merge 2 commits into
egoist:mainfrom
yaffalhakim1:fix/local-daemon-socket-reconnect

Conversation

@yaffalhakim1

Copy link
Copy Markdown

Fixes #178

Problem

A transient drop of the desktop-to-daemon WebSocket (suspend/resume, a socket reset) leaves the desktop permanently disconnected on Windows while waku-daemon.exe keeps running. monitor_daemon reconnects Remote targets, but for Local targets it only checks whether the child process exited. A live child with a dead client socket never recovers, and every save afterwards repeats "Could not save local state: Waku daemon is disconnected" until the user restarts the app.

Solution

The supervisor now treats a disconnected local client the way it already treats a disconnected remote client: it opens a replacement DaemonClient against the same listener, replays the last cursors, and publishes it through the supervisor. The daemon process itself is left untouched, so provider runtimes survive the reconnect.

  • DaemonProcess records the address it connected to and can swap its client.
  • DaemonTarget::Local carries the address and token, so the monitor can reconnect without re-reading exposure settings.
  • monitor_daemon gains a local reconnect path mirroring the existing remote one. The decision and the swap live in local_reconnect_params, replace_local_client, and try_local_reconnect, which take an injected connector and stay unit-testable.
  • DaemonClient::disconnected_for_test (test-only) builds a client marked disconnected with given replay cursors.

Checks

  • cargo fmt -p waku-client -- --check
  • cargo check -p waku-client
  • cargo test -p waku-client: 22 passed, 5 new tests covering the reconnect decision, target filtering, client swap, and the injected connector

Limitations

The new tests cover the reconnect decision and client replacement, not a full lifecycle against a real daemon process. A lifecycle test would need a mock daemon binary, so I kept this patch focused. Some app-state holders capture daemon.client() once and keep the old handle after a reconnect; task-state sync already follows subscribe_clients, so the save path recovers immediately.

monitor_daemon reconnected Remote targets but only checked whether a
Local child process had exited. A live daemon with a dead client socket
left the desktop stuck on 'daemon is disconnected' until restart
(egoist#178). The supervisor now opens a replacement client against
the same listener with the last replay cursors and publishes it through
the supervisor, mirroring the remote reconnect path.
Extend UsageProvider to OpenCode/OpenCode2. The usage scan now reads
OpenCode's session/session_v2 tables (per-session token + cost aggregates)
instead of JSONL transcripts, so OpenCode usage finally appears in
Settings > Usage. Generalize the Usage page charts, provider colors, and
split bars to N providers (the canvas renderers were already generic).

- waku-protocol: add OpenCode/OpenCode2 variants; grow DaySlice/MonthSlice/
  ProjectSlice by_provider arrays to 4.
- waku-core: add provider_db_path + read_opencode_db (read-only SQLite, model
  JSON unwrapped to its id, dedupe_key = session id); branch the scan loop
  for SQLite-backed providers; fix ProjectAccumulator array size.
- usage_page: map provider_kind; build provider colors/series/split bars from
  UsageProvider::ALL.
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.

Local daemon WebSocket disconnect leaves desktop unable to save state

1 participant