http: sticky echo headers + Fly.io quickstart helpers#10
Merged
Conversation
|
|
5 tasks
Server-side ``sticky_echo_headers={name: value}`` config tells the client
to replay arbitrary headers on every subsequent request in the session.
Emitted once-only as ``VGI-Echo-<name>: <value>`` on session-opening
responses; client captures + replays automatically inside the
``with_session_token()`` view. Used for client-driven routing on
platforms like Fly.io — ``vgi_rpc.http.fly.fly_sticky_echo_headers()``
returns ``{"fly-force-instance-id": $FLY_MACHINE_ID}`` so fly-proxy
routes directly to the owning Machine with zero LB config.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ec11d3f to
726173c
Compare
rustyconover
added a commit
that referenced
this pull request
May 18, 2026
API Reference entries for surfaces introduced in #9/#10/#11: * http.md gains ``serve_http`` (was missing), ``DrainHandle``, ``drain_handle``, and the ``vgi_rpc.http.fly`` quickstart helpers. * core.md "Errors" gains a "Typed marker errors" subsection covering ``MethodNotImplementedError`` (pre-existing miss), ``SessionLostError``, and ``ServerDrainingError`` — the three classes carrying ``error_kind`` for wire-side pattern matching. mkdocs --strict builds clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
rustyconover
added a commit
that referenced
this pull request
May 18, 2026
Feature release. Adds opt-in sticky sessions for the HTTP transport (PRs #9, #10, #11). Non-sticky wire path byte-identical to 0.16.1; existing callers see no behaviour change. * ctx.open_session / ctx.close_session runtime API on CallContext * with conn.with_session_token() as sess: client view * VGI-Session header transport with AEAD-sealed token, principal-bound AAD * DELETE /vgi/__session__ idempotent teardown endpoint * sticky_echo_headers — server-issued headers the client replays (Fly.io quickstart helpers in vgi_rpc.http.fly) * drain_handle(app) operator API + serve_http SIGTERM graceful drain * Access-log session_id + session_action fields * Typed errors SessionLostError + ServerDrainingError * Canonical TestSticky cross-language conformance group (11 tests, capability-gated) * Full spec at docs/sticky-sessions-spec.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
sticky-sessions-coreso it'll cleanly rebase ontomainonce http: opt-in sticky sessions (HTTP-only, header transport, DELETE endpoint) #9 merges.sticky_echo_headers={name: value}onmake_wsgi_apptells the client to echo arbitrary headers on every subsequent request in the session. Used for client-driven routing on platforms like Fly.io.vgi_rpc/http/fly.py(~25 lines):auto_server_id()+fly_sticky_echo_headers()— Fly.io quickstart helpers. Two-line setup, zero LB config.VGI-Sticky-Echo-Headersadvertises the configured names;HttpServerCapabilities.sticky_echo_headers: tuple[str, ...]surfaces them.TestSticky::test_echo_header_round_trip(capability-gated onVGI-Sticky-Echo-Headersso deployments without echo support skip cleanly).Wire contract
Server side: when
sticky_echo_headers={"fly-force-instance-id": \"abc\"}is configured, every session-opening response carriesVGI-Echo-fly-force-instance-id: abc. Emitted once only — subsequent responses MUST NOT re-emit. Capability headerVGI-Sticky-Echo-Headers: fly-force-instance-idadvertises the contract.Client side:
with_session_token()view's_SessionTrackingClientcaptures everyVGI-Echo-<name>response header (case-insensitive, prefix-stripped) and replays the inner header on every subsequent request in the same block. Captured map exposed viasess.current_echo_headers(); cleared onVGI-Session-Close: true.Caller-supplied request headers take precedence:
_merge_headersusessetdefault, so passing an explicit per-call header overrides the captured echo header for that one request.Fly quickstart
Off Fly both helpers return
Noneso the same code is a no-op — no conditional branches.Test plan
uv run ruff format .uv run ruff check .→ cleanuv run mypy vgi_rpc/→ cleanuv run ty check vgi_rpc/→ clean (pre-existing pyarrow note only)uv run pytest --timeout=50→ 3316 passed, 0 failed in ~82sTestStickytests pass (was 9 in PR1; +1 echo round-trip)What's next
RpcServer.drain()+ SIGTERM handler +drain_grace_seconds+ access-logsession_id/session_actionfields). Independent of this PR.🤖 Generated with Claude Code