Skip to content

fix: await owned daemon retirement on request timeout - #3131

Closed
thymikee wants to merge 2 commits into
fix/daemon-startup-contentionfrom
fix/daemon-timeout-retirement
Closed

thymikee wants to merge 2 commits into
fix/daemon-startup-contentionfrom
fix/daemon-timeout-retirement

Conversation

@thymikee

@thymikee thymikee commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Summary

A local request timeout could remove daemon metadata before its daemon exited. Socket and HTTP timeouts now await the same ownership-checked retirement operation before reporting reset. Unconfirmed exit retains state and is included in the primary timeout error.

Removes the client’s raw metadata-removal and takeover-stop exports. Read-only command policies, remote behavior, Apple runner pattern bytes and request fallback rules stay intact. Health probes reserve time for a fallback and count requester loading and response completion within their budget.

Depends on #3130. Ref #3116. Eight files, 616 gross changed lines; production: 107 additions/143 deletions. The final enforcement commit acknowledges one implementation-only health-reader change, with no RPC payload or protocol-version change.

Validation

Tested 2afb5ec51ab198cc380f6db6a2c6d88d44965241:

  • 61 focused tests, including actual socket/HTTP requests and owned children; zero skips.
  • Removing the await fails both force-retirement controls. Removing fallback reservation or loader accounting each fails its control.
  • Remaining retirement-owner tests catch premature unlink: 31 passes → 3 failures/28 passes. Obsolete wrapper tests and seams were removed together.
  • 42 wire compatibility/closure/mutation controls pass.
  • pnpm check:quick, Fallow, and pnpm check:affected --base fix/daemon-startup-contention --run pass; 925 related tests.
  • Independent read-only review: no findings. CI-owned coverage, provider and device evidence remains pending.

Review in cubic

@github-actions

github-actions Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
Installed (including dependencies) 4.96 MB 4.96 MB +499 B
Package (unpacked) 4.95 MB 4.96 MB +499 B
Package (download) 1.49 MB 1.49 MB +111 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 27.1 ms 26.7 ms -0.4 ms
CLI --help 83.4 ms 82.1 ms -1.3 ms

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 8 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/daemon-client/daemon-client-timeout.ts
Comment thread src/daemon-client/__tests__/daemon-client-timeout-route.test.ts
Comment thread src/daemon-client/__tests__/daemon-client-lifecycle.test.ts
@thymikee

thymikee commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

This PR is ready at 2afb5ec. The change now waits for the owned daemon to retire after a request timeout, and I found no problem in the code.

Not blocking, and you can take or leave these: (1) the local retirement branch in https://github.com/callstack/agent-device/blob/2afb5ec/src/daemon-client/daemon-client-transport.ts#L269 keys on the public daemon_transport_timeout reason, so only a timer this client armed should trigger it, for example through a module-private error class that requestTimeoutError creates and the sendRequest catch checks with instanceof; (2) the halved canConnect budget and the health-probe race in https://github.com/callstack/agent-device/blob/2afb5ec/src/daemon-client/daemon-client-transport.ts#L79 look like the startup-deadline work from #3130, so could that move there or be named in the summary; (3) the hint in https://github.com/callstack/agent-device/blob/2afb5ec/src/daemon-client/daemon-client-timeout.ts#L110 always says the daemon could not be safely retired, even when the daemon was killed and the result is lock-busy or registration-replaced, and it drops the Apple cleanup wording, so the wording could follow retirement.reason; (4) the timeout error now returns after the request budget plus up to 1s for exit after SIGKILL and up to 1s for the retirement lock, which is bounded but not documented or asserted.

CI is likely unrelated to this change. The Coverage failure is the slow-test gate on daemon-client-startup-race.test.ts:207 ("startup uses one deadline when the claim is held"), which came in with #3130 and is unchanged here. Its held-claim route never publishes daemon.json, so it never reaches canConnect or sendRequest. The Smoke failure is the iOS preflight daemon_startup_failed with hasInfo:false, so the daemon never published its registration within the 15s budget. The changed canConnect only runs after that info exists, so the changed probe was not reached. The same signature appears on #3129.

I did not run the mutations the PR describes (removing the await, the fallback reservation, the loader accounting). I judged the regression tests from a read of the pre-change code. I could not confirm that #3129 lacks this PR's canConnect change, so the Smoke attribution rests on the hasInfo:false evidence. I also did not confirm the Coverage failure on #3130's own CI run, so "inherited" rests on file and route provenance.

No conflicts. Before merge, the Coverage failure must be fixed in #3130 by injecting the startup clock or poll budget. Then Smoke should be rerun after #3130 lands.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Oct 3, 2026
@thymikee
thymikee added this pull request to stack #3146 October 3, 2026 08:46
@thymikee
thymikee force-pushed the fix/daemon-startup-contention branch from 180ee97 to 6e44617 Compare October 3, 2026 14:40
@thymikee
thymikee force-pushed the fix/daemon-timeout-retirement branch 2 times, most recently from 4fd7029 to 814fb0c Compare October 3, 2026 16:41
@thymikee
thymikee force-pushed the fix/daemon-startup-contention branch from 6e44617 to 83de7a2 Compare October 3, 2026 16:41
@thymikee
thymikee force-pushed the fix/daemon-timeout-retirement branch from 814fb0c to bcce61b Compare October 3, 2026 17:49
@thymikee
thymikee force-pushed the fix/daemon-startup-contention branch from 83de7a2 to 745589d Compare October 3, 2026 17:49
@thymikee
thymikee removed this pull request from stack #3146 October 3, 2026 19:38
@thymikee
thymikee force-pushed the fix/daemon-startup-contention branch from 745589d to d2c7a19 Compare October 3, 2026 19:39
@thymikee
thymikee force-pushed the fix/daemon-timeout-retirement branch from bcce61b to 50eafe5 Compare October 3, 2026 19:39
@thymikee
thymikee added this pull request to stack #3187 October 3, 2026 19:45
@thymikee
thymikee removed this pull request from stack #3187 October 3, 2026 20:58
@thymikee

thymikee commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

Consolidated into #3127 as part of reducing #3116 to seven PRs. The composition preserves the complete pre-consolidation source tree, including tests and later review corrections. This PR is superseded; its review discussion and native evidence remain available. Outstanding findings transfer to the owning keeper in the implementation record.

@thymikee thymikee closed this Oct 3, 2026
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-10-03 21:16 UTC

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

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant