Skip to content

feat(sdk): route Go SDK exec and forward to the sandbox owner replica - #4852

Merged
FrostGod merged 3 commits into
NVIDIA:mainfrom
FrostGod:feat/4223-go-sdk-replica-routing/FrostGod
Oct 29, 2026
Merged

FrostGod merged 3 commits into
NVIDIA:mainfrom
FrostGod:feat/4223-go-sdk-replica-routing/FrostGod

Conversation

@FrostGod

Copy link
Copy Markdown
Collaborator

Summary

The Go SDK now sends exec, port-forward, and SSH tunnel calls straight to the gateway replica that owns the sandbox's supervisor session, as the CLI already does. Behind an edge proxy with replica routing enabled, this skips the relay hop through a peer replica; without one, the header is ignored and behavior is unchanged.

Related Issue

Part of #4223 (the "Every SDK asks for the owner and sends the replica hint, like the CLI" item, Go portion). Rust is #4790; TypeScript and Python follow in separate PRs.

Changes

  • Exec.Run, Exec.Stream, Exec.Interactive, TCP.Forward, and SSH.Tunnel already call GetSandbox first; that call now also asks for the owner, so no round trip is added.
  • New private routing.go: sends x-openshell-replica on those streams and retries once without it when Envoy reports the owner's route has no ready endpoints (same rule as the CLI). Forward and interactive calls resend their init frame on retry.
  • Calls are unchanged when the gateway reports no owner.

Release Notes

Go SDK exec, port-forward, and SSH tunnel calls now take the direct route to the sandbox's owner replica when replica routing is enabled.

Testing

  • Checks appropriate to the affected code and behavior pass (mise run go:ci: format, build, lint, tests, proto and docs checks)
  • Unit tests added/updated (bufconn mock gateway: routing to the owner, no hint without an owner, one unrouted retry for exec/stream/interactive/forward, no retry on gateway errors, retry rule)
  • E2E tests added/updated (if applicable). Manual check on a local k3s VM (Ubuntu 26.04, Landlock-capable kernel) with Envoy Gateway and two StatefulSet replicas, using a real sandbox and supervisor session: every SDK call type ran its command and landed on the owner replica (unhinted baseline split 6/4), still succeeded via unrouted retry and peer relay when the owner's route had no endpoints, and followed the owner to the other replica after a gateway restart.

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

@copy-pr-bot

copy-pr-bot Bot commented Oct 22, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@EmilienM EmilienM 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.

Needs a human read: 8 minor (inline, 1 below)

No blocking or major findings: this is a faithful port of the CLI's shipped design, and the grpc-go Header()/RecvMsg(nil) handling checks out against v1.83.2. Deep-tier review on code changes, so the verdict stays with a human.

Outside the diff:

  • Minor: docs/kubernetes/ingress.mdx:260, the docs still say only the CLI sets the replica header; a one-sentence update should include the Go SDK.
How this was reviewed
  • Commit 32b34f8f, round 1
  • Deep review, because of sdk/go/openshell/v1/routing.go, exec_client.go, tcp_client.go
  • Passes: architecture, performance, security, scalability, then correctness
  • Independent skeptics checked each candidate finding (2 for the major, 1 for minor ones); 5 of 7 held up
  • Repo rules read from 9a85667d: AGENTS.md, CLAUDE.md, CONTRIBUTING.md, docs/CONTRIBUTING.mdx
  • Not covered: nothing skipped

Comment thread sdk/go/openshell/v1/routing.go
Comment thread sdk/go/openshell/v1/routing.go
Comment thread sdk/go/openshell/v1/routing.go
Comment thread sdk/go/openshell/v1/routing.go Outdated
Comment thread sdk/go/openshell/v1/exec_client.go Outdated
Comment thread sdk/go/openshell/v1/exec_client.go Outdated
Comment thread sdk/go/openshell/v1/sandbox_client.go
@FrostGod

Copy link
Copy Markdown
Collaborator Author

/ok to test afd6b1e

pimlock
pimlock previously approved these changes Oct 28, 2026
@FrostGod
FrostGod enabled auto-merge October 28, 2026 21:49
@FrostGod
FrostGod added this pull request to the merge queue Oct 28, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 28, 2026
The Go SDK now does what the CLI already does for long-lived sandbox
calls. The GetSandbox check that Exec.Run, Exec.Stream, Exec.Interactive,
TCP.Forward and SSH.Tunnel already make also asks the gateway for the
owner replica. The call then sends it in the x-openshell-replica header
and retries once without the header when the edge proxy reports that the
owner's route has no ready endpoints.

No extra round trip is added. Without a reported owner the calls are
unchanged.

Part of NVIDIA#4223

Signed-off-by: divesh <dgude@nvidia.com>
Share the header check between the routed attempt and its retry, keep the
first-frame EOF rule in one bidi helper, reuse Get's request for the owner
lookup, and document the header contract next to the replica routing docs.

Part of NVIDIA#4223

Signed-off-by: divesh <dgude@nvidia.com>
@FrostGod
FrostGod force-pushed the feat/4223-go-sdk-replica-routing/FrostGod branch from afd6b1e to 34ad211 Compare October 29, 2026 00:43
@TaylorMutch

Copy link
Copy Markdown
Collaborator

/ok to test 34ad211

Comment thread docs/kubernetes/ingress.mdx Outdated
@TaylorMutch

Copy link
Copy Markdown
Collaborator

Otherwise LGTM

TaylorMutch
TaylorMutch previously approved these changes Oct 29, 2026
@FrostGod

Copy link
Copy Markdown
Collaborator Author

/ok to test 4655179

@github-actions

Copy link
Copy Markdown

Compatibility review (advisory)

New or updated breaking changes; see the full report for all findings.

1. go-sdk — No explicit risk acceptance found

Exec.Interactive, TCP.Forward, and SSH.Tunnel previously returned handles after sending initialization; owner-routed calls now wait for response headers.

  • Impact: Clients using owner-reporting gRPC servers or mocks that defer headers until output now hang before obtaining the handle needed to send the awaited input.
  • Action: Preserve input-first operation without requiring existing servers to flush headers early; documenting intentional waiting does not address this Stable API break in a patch train.
  • PR: feat(sdk): route Go SDK exec and forward to the sandbox owner replica #4852
Review details
  • Execution: complete
  • Candidate: PR #4852 (8fd740d083f1eb6d8a1304cf47969ff9490ef3fb)
  • Baseline: 677875fd034e25906ec95c82a7ccc27ba04cf589 (677875fd034e25906ec95c82a7ccc27ba04cf589)
  • Reviewed: rust-sdk, python-sdk, go-sdk, typescript-sdk, api-behavior, cli, configuration, policy, helm, state

Advisory review; publication gates are unchanged.

Branch check run

@FrostGod
FrostGod added this pull request to the merge queue Oct 29, 2026
Merged via the queue into NVIDIA:main with commit cc99954 Oct 29, 2026
84 of 86 checks passed
@FrostGod
FrostGod deleted the feat/4223-go-sdk-replica-routing/FrostGod branch October 29, 2026 17:41
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.

4 participants