Skip to content

refactor(rpc): services take the api options object - #919

Merged
omartelo merged 1 commit into
mainfrom
refactor/service-options
Oct 23, 2026
Merged

omartelo merged 1 commit into
mainfrom
refactor/service-options

Conversation

@omartelo

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #917. Every service method a route exposes now has the shape of the method api declares, func(context.Context, api.XOptions) (Result, error), and every route is rpc.Handle(d, api.X, s.Method). internal/routes holds no adapter closure: a service and its wire shape can no longer drift apart behind one.

  • Methods that cannot fail (26, e.g. Live, Exists, Verify, Status) keep their body as an unexported method their own package calls; the exported method is the RPC shape around it.
  • Callers in other packages handle the error like any other call. Where there is nowhere to return it, it is logged and the safe answer taken: relay's ticket sweep keeps the errand, the merge notice leaves the session out, the tray keeps its title, the window-failed dialog does not quit, the rage report shows its "no data" row.
  • Interfaces over these services (terminal.Store, relay.Terminal, spawn.Sessions, themes.Settings, ...) and their fakes moved with them.
  • terminal.spawnSession takes the StartOptions instead of ten positional arguments; godocs name opts fields instead of parameters that are gone.
  • CLAUDE.md's RPC rule says the routed method has this shape.

The wire did not move: api/ and api/testdata/contract.golden are untouched, and native/ is unchanged.

Test changed

TestHandleProfilesCoverEveryProfileMethod registers typed nil services instead of a nil interface: a route now reads its method value when it is registered, which a nil interface does not have. The test assumed something the contract never promised. Every other test change follows the new signatures, no assertion loosened.

Test plan

  • gofmt, go vet ./..., go test ./... (3927 passed, coverage 91.1%)
  • Cross-compile and vet for linux, darwin, windows; -tags installer_e2e
  • Rig on its own backend in a virtual display: window attach, session start, diff/branch footer; 50 RPC calls across every service, including a positional call refused with 400; CLI open, rename, file, rename-folder, insert, focus, theme switch, cost, close; MCP list_sessions

Every routed service method now has the shape of the method api declares,
func(context.Context, api.XOptions) (Result, error), and every route hands it
over as s.Method: internal/routes holds no adapter closure any more, so a
service and its wire shape can no longer drift apart behind one.

- A method that cannot fail keeps its body as an unexported method its own
  package calls; the exported one is the RPC shape around it. Callers in other
  packages handle the error like any other call; where there is nowhere to
  return it (relay's ticket sweep and merge audience, the tray title, the
  window-failed dialog, the rage report) it is logged and the safe answer
  taken.
- Interfaces over these services (terminal.Store, relay.Terminal,
  spawn.Sessions, themes.Settings, ...) and their fakes moved with them.
- terminal.spawnSession takes the StartOptions instead of ten positional
  arguments; godocs name opts fields instead of parameters that are gone.
- The profiles route test registers typed nil services: a route reads its
  method value when it is registered, which a nil interface does not have.
  The test assumed something the contract never promised.

The wire did not move: api/ and contract.golden are untouched.
@omartelo
omartelo merged commit 09d1c26 into main Oct 23, 2026
7 checks passed
@omartelo
omartelo deleted the refactor/service-options branch October 23, 2026 13:12
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.

1 participant