Skip to content

feat(bigtable): Use direct access if it returns true. Guarded by CBT_BIGTABLE_CONN_POOL - #7

Open
sushanb wants to merge 4 commits into
health_check_from
opt_conn
Open

sushanb wants to merge 4 commits into
health_check_from
opt_conn

Conversation

@sushanb

@sushanb sushanb commented Jan 7, 2026

Copy link
Copy Markdown
Owner

Notes.

The current metric for directpath eligiblity is async via periodic flush.

In future cl, We will make it synchronous and use direct acces only if

  1. if prime() succeeds within 10s
  2. If synchrous metrics flush for directpath elibility succeeds.

@sushanb
sushanb requested a review from nimf January 7, 2026 05:33
sushanb added a commit that referenced this pull request Jul 20, 2026
Prior to this change, heartBeatLoop's Timer was armed once at Start to
initialHeartbeatGrace (30 min) and only reshuffled after it fired.
The atomic nextHeartbeatDeadlineNano was extended by every frame per
SESSION_SPEC.md #7, but a later SessionParameters frame that shortened
the interval to, say, KeepAlive=100ms would leave the Timer sleeping
past its now-relevant deadline — a stalled vRPC in the first 30 min
was caught by the caller's ctx, not by the missed-heartbeat watchdog.

Add a cap-1 non-blocking heartbeatWake channel; handleSessionParameters
and resetHeartbeatDeadline both fire it after updating the atomic.
heartBeatLoop's select now watches the wake alongside timer.C, stops
and drains the Timer on wake, then re-evaluates against the current
atomic. Bursts of wakes coalesce into one pending signal, so hot-path
frame handling stays allocation-free.

Behavioral impact: missed-heartbeat ForceClose now fires within
~3×interval of the last frame regardless of whether the initial-grace
Timer has fired. Retry oracle re-picks a peer session as before
(StateTransportFailure + Unavailable, idempotent retry).

Follow-ups deferred: the wake fires on every reset, including
extension-only resets that the Timer would learn about naturally on
next fire. A shrink-only CAS gate is a natural optimization but not a
correctness item — see [[bigtable-reactive-heartbeat-followups]].
sushanb added a commit that referenced this pull request Jul 23, 2026
…Loop, heartBeatLoop)

Third and final PR in the Session core stack. Adds the lifecycle
orchestration that drives a Session from Start through teardown, plus
the readLoop that dispatches server frames to the vRPC handlers landed
in bigtable-session-vrpc.

Stacks on bigtable-session-vrpc; deletes the minimal ForceClose stub
that PR shipped, replacing it with the full lifecycle-shaped body.

New file: session_lifecycle.go (~640 LOC)
- Session.Start(ctx, OpenSessionRequest) — transitions New→Starting,
  Sends the OpenSession frame, fires onStart, spawns readLoop +
  heartBeatLoop. Wraps a failed Send as codes.Unavailable so retry
  plumbing treats pre-wire OpenSession loss the same as any other
  transport-side loss.
- ForceClose — full body: transitionTo(Closed), setCloseReason,
  notifyClosing (once), cancelActiveRPCs, signalQuiescent, notifyClosed.
- Close(ctx, CloseSessionRequest) — graceful drain: Ready→Closing,
  waits on quiescent, sends CloseSession, transitions to
  WaitServerClose, arms the pool's stuck-session sweep to eventually
  ForceClose if the server never confirms.
- notifyClosing / notifyClosed — once-guarded hook dispatchers with
  the strict onClosing-precedes-onClose ordering enforced.
- readLoop(ctx) — Recv-loop that dispatches every SessionResponse
  variant via handleSessionResponse, drives handleClose on stream
  termination, records msgsRecv counters + resets heartbeat deadline
  on every recognized frame.
- handleSessionResponse — dispatch switch to
  handleOpenSession / handleVRPCResponse / handleErrorResponse /
  handleSessionParameters / handleGoAway / handleSessionRefreshConfig.
  Heartbeat frames update the deadline via resetHeartbeatDeadline; the
  unknown-payload branch records a debug tag but doesn't reset the
  deadline (so a misbehaving server can't keep the watchdog satisfied
  with junk).
- handleOpenSession — Starting→Ready transition, PeerInfo extract
  from the bidi header (synchronous, matches Java's onHeaders
  synchrony), fires onActive.
- handleGoAway / handleClose / handleErrorResponse / handleSessionParameters
  / handleSessionRefreshConfig — protocol-level handlers.
- heartBeatLoop — Timer + heartbeatWake reactive-wake pair. Only
  enforces the deadline while a vRPC is in flight (idle sessions
  legitimately receive no server heartbeats). See SESSION_SPEC.md #7.
- peerInfoExtracter — parses the bigtable-peer-info header, stamps
  s.peerInfo atomically before onActive fires.
- closeReasonLabel / closeReasonToCause — CloseSessionRequest.Reason
  → string / sentinel error mapping for close-reason attribution.

New file: session_lifecycle_test.go (~660 LOC) — 30+ tests covering
Start, ForceClose, Close, readLoop, handleSessionResponse dispatch,
handleOpenSession + peerInfo parsing, handleGoAway, handleClose,
handleErrorResponse (rpc_id=0 harmlessly drops via routeVRPCFrame
guards), heartBeatLoop (reactive wake, idle-gate, missed-heartbeat
ForceClose).

Edits to session_vrpc.go
- Delete the minimal ForceClose stub introduced in the prior PR —
  the full body lives in session_lifecycle.go now.

Edits to session_test.go
- Add hookCounts helper (start/active/close callback counters).
- Add setSlotForTest helper (seed the in-flight slot from tests).

Stack:
- googleapis#20211 — Session debug surface
- googleapis#20213 — Session vRPC dispatch + slot lifecycle
- This PR — Session lifecycle
sushanb added a commit that referenced this pull request Jul 23, 2026
…Loop, heartBeatLoop)

Third and final PR in the Session core stack. Adds the lifecycle
orchestration that drives a Session from Start through teardown, plus
the readLoop that dispatches server frames to the vRPC handlers landed
in bigtable-session-vrpc.

Stacks on bigtable-session-vrpc; deletes the minimal ForceClose stub
that PR shipped, replacing it with the full lifecycle-shaped body.

New file: session_lifecycle.go (~640 LOC)
- Session.Start(ctx, OpenSessionRequest) — transitions New→Starting,
  Sends the OpenSession frame, fires onStart, spawns readLoop +
  heartBeatLoop. Wraps a failed Send as codes.Unavailable so retry
  plumbing treats pre-wire OpenSession loss the same as any other
  transport-side loss.
- ForceClose — full body: transitionTo(Closed), setCloseReason,
  notifyClosing (once), cancelActiveRPCs, signalQuiescent, notifyClosed.
- Close(ctx, CloseSessionRequest) — graceful drain: Ready→Closing,
  waits on quiescent, sends CloseSession, transitions to
  WaitServerClose, arms the pool's stuck-session sweep to eventually
  ForceClose if the server never confirms.
- notifyClosing / notifyClosed — once-guarded hook dispatchers with
  the strict onClosing-precedes-onClose ordering enforced.
- readLoop(ctx) — Recv-loop that dispatches every SessionResponse
  variant via handleSessionResponse, drives handleClose on stream
  termination, records msgsRecv counters + resets heartbeat deadline
  on every recognized frame.
- handleSessionResponse — dispatch switch to
  handleOpenSession / handleVRPCResponse / handleErrorResponse /
  handleSessionParameters / handleGoAway / handleSessionRefreshConfig.
  Heartbeat frames update the deadline via resetHeartbeatDeadline; the
  unknown-payload branch records a debug tag but doesn't reset the
  deadline (so a misbehaving server can't keep the watchdog satisfied
  with junk).
- handleOpenSession — Starting→Ready transition, PeerInfo extract
  from the bidi header (synchronous, matches Java's onHeaders
  synchrony), fires onActive.
- handleGoAway / handleClose / handleErrorResponse / handleSessionParameters
  / handleSessionRefreshConfig — protocol-level handlers.
- heartBeatLoop — Timer + heartbeatWake reactive-wake pair. Only
  enforces the deadline while a vRPC is in flight (idle sessions
  legitimately receive no server heartbeats). See SESSION_SPEC.md #7.
- peerInfoExtracter — parses the bigtable-peer-info header, stamps
  s.peerInfo atomically before onActive fires.
- closeReasonLabel / closeReasonToCause — CloseSessionRequest.Reason
  → string / sentinel error mapping for close-reason attribution.

New file: session_lifecycle_test.go (~660 LOC) — 30+ tests covering
Start, ForceClose, Close, readLoop, handleSessionResponse dispatch,
handleOpenSession + peerInfo parsing, handleGoAway, handleClose,
handleErrorResponse (rpc_id=0 harmlessly drops via routeVRPCFrame
guards), heartBeatLoop (reactive wake, idle-gate, missed-heartbeat
ForceClose).

Edits to session_vrpc.go
- Delete the minimal ForceClose stub introduced in the prior PR —
  the full body lives in session_lifecycle.go now.

Edits to session_test.go
- Add hookCounts helper (start/active/close callback counters).
- Add setSlotForTest helper (seed the in-flight slot from tests).

Stack:
- googleapis#20211 — Session debug surface
- googleapis#20213 — Session vRPC dispatch + slot lifecycle
- This PR — Session lifecycle
sushanb added a commit that referenced this pull request Jul 24, 2026
…Loop, heartBeatLoop)

Third and final PR in the Session core stack. Adds the lifecycle
orchestration that drives a Session from Start through teardown, plus
the readLoop that dispatches server frames to the vRPC handlers landed
in bigtable-session-vrpc.

Stacks on bigtable-session-vrpc; deletes the minimal ForceClose stub
that PR shipped, replacing it with the full lifecycle-shaped body.

New file: session_lifecycle.go (~640 LOC)
- Session.Start(ctx, OpenSessionRequest) — transitions New→Starting,
  Sends the OpenSession frame, fires onStart, spawns readLoop +
  heartBeatLoop. Wraps a failed Send as codes.Unavailable so retry
  plumbing treats pre-wire OpenSession loss the same as any other
  transport-side loss.
- ForceClose — full body: transitionTo(Closed), setCloseReason,
  notifyClosing (once), cancelActiveRPCs, signalQuiescent, notifyClosed.
- Close(ctx, CloseSessionRequest) — graceful drain: Ready→Closing,
  waits on quiescent, sends CloseSession, transitions to
  WaitServerClose, arms the pool's stuck-session sweep to eventually
  ForceClose if the server never confirms.
- notifyClosing / notifyClosed — once-guarded hook dispatchers with
  the strict onClosing-precedes-onClose ordering enforced.
- readLoop(ctx) — Recv-loop that dispatches every SessionResponse
  variant via handleSessionResponse, drives handleClose on stream
  termination, records msgsRecv counters + resets heartbeat deadline
  on every recognized frame.
- handleSessionResponse — dispatch switch to
  handleOpenSession / handleVRPCResponse / handleErrorResponse /
  handleSessionParameters / handleGoAway / handleSessionRefreshConfig.
  Heartbeat frames update the deadline via resetHeartbeatDeadline; the
  unknown-payload branch records a debug tag but doesn't reset the
  deadline (so a misbehaving server can't keep the watchdog satisfied
  with junk).
- handleOpenSession — Starting→Ready transition, PeerInfo extract
  from the bidi header (synchronous, matches Java's onHeaders
  synchrony), fires onActive.
- handleGoAway / handleClose / handleErrorResponse / handleSessionParameters
  / handleSessionRefreshConfig — protocol-level handlers.
- heartBeatLoop — Timer + heartbeatWake reactive-wake pair. Only
  enforces the deadline while a vRPC is in flight (idle sessions
  legitimately receive no server heartbeats). See SESSION_SPEC.md #7.
- peerInfoExtracter — parses the bigtable-peer-info header, stamps
  s.peerInfo atomically before onActive fires.
- closeReasonLabel / closeReasonToCause — CloseSessionRequest.Reason
  → string / sentinel error mapping for close-reason attribution.

New file: session_lifecycle_test.go (~660 LOC) — 30+ tests covering
Start, ForceClose, Close, readLoop, handleSessionResponse dispatch,
handleOpenSession + peerInfo parsing, handleGoAway, handleClose,
handleErrorResponse (rpc_id=0 harmlessly drops via routeVRPCFrame
guards), heartBeatLoop (reactive wake, idle-gate, missed-heartbeat
ForceClose).

Edits to session_vrpc.go
- Delete the minimal ForceClose stub introduced in the prior PR —
  the full body lives in session_lifecycle.go now.

Edits to session_test.go
- Add hookCounts helper (start/active/close callback counters).
- Add setSlotForTest helper (seed the in-flight slot from tests).

Stack:
- googleapis#20211 — Session debug surface
- googleapis#20213 — Session vRPC dispatch + slot lifecycle
- This PR — Session lifecycle
sushanb added a commit that referenced this pull request Jul 24, 2026
…Loop, heartBeatLoop)

Third and final PR in the Session core stack. Adds the lifecycle
orchestration that drives a Session from Start through teardown, plus
the readLoop that dispatches server frames to the vRPC handlers landed
in bigtable-session-vrpc.

Stacks on bigtable-session-vrpc; deletes the minimal ForceClose stub
that PR shipped, replacing it with the full lifecycle-shaped body.

New file: session_lifecycle.go (~640 LOC)
- Session.Start(ctx, OpenSessionRequest) — transitions New→Starting,
  Sends the OpenSession frame, fires onStart, spawns readLoop +
  heartBeatLoop. Wraps a failed Send as codes.Unavailable so retry
  plumbing treats pre-wire OpenSession loss the same as any other
  transport-side loss.
- ForceClose — full body: transitionTo(Closed), setCloseReason,
  notifyClosing (once), cancelActiveRPCs, signalQuiescent, notifyClosed.
- Close(ctx, CloseSessionRequest) — graceful drain: Ready→Closing,
  waits on quiescent, sends CloseSession, transitions to
  WaitServerClose, arms the pool's stuck-session sweep to eventually
  ForceClose if the server never confirms.
- notifyClosing / notifyClosed — once-guarded hook dispatchers with
  the strict onClosing-precedes-onClose ordering enforced.
- readLoop(ctx) — Recv-loop that dispatches every SessionResponse
  variant via handleSessionResponse, drives handleClose on stream
  termination, records msgsRecv counters + resets heartbeat deadline
  on every recognized frame.
- handleSessionResponse — dispatch switch to
  handleOpenSession / handleVRPCResponse / handleErrorResponse /
  handleSessionParameters / handleGoAway / handleSessionRefreshConfig.
  Heartbeat frames update the deadline via resetHeartbeatDeadline; the
  unknown-payload branch records a debug tag but doesn't reset the
  deadline (so a misbehaving server can't keep the watchdog satisfied
  with junk).
- handleOpenSession — Starting→Ready transition, PeerInfo extract
  from the bidi header (synchronous, matches Java's onHeaders
  synchrony), fires onActive.
- handleGoAway / handleClose / handleErrorResponse / handleSessionParameters
  / handleSessionRefreshConfig — protocol-level handlers.
- heartBeatLoop — Timer + heartbeatWake reactive-wake pair. Only
  enforces the deadline while a vRPC is in flight (idle sessions
  legitimately receive no server heartbeats). See SESSION_SPEC.md #7.
- peerInfoExtracter — parses the bigtable-peer-info header, stamps
  s.peerInfo atomically before onActive fires.
- closeReasonLabel / closeReasonToCause — CloseSessionRequest.Reason
  → string / sentinel error mapping for close-reason attribution.

New file: session_lifecycle_test.go (~660 LOC) — 30+ tests covering
Start, ForceClose, Close, readLoop, handleSessionResponse dispatch,
handleOpenSession + peerInfo parsing, handleGoAway, handleClose,
handleErrorResponse (rpc_id=0 harmlessly drops via routeVRPCFrame
guards), heartBeatLoop (reactive wake, idle-gate, missed-heartbeat
ForceClose).

Edits to session_vrpc.go
- Delete the minimal ForceClose stub introduced in the prior PR —
  the full body lives in session_lifecycle.go now.

Edits to session_test.go
- Add hookCounts helper (start/active/close callback counters).
- Add setSlotForTest helper (seed the in-flight slot from tests).

Stack:
- googleapis#20211 — Session debug surface
- googleapis#20213 — Session vRPC dispatch + slot lifecycle
- This PR — Session lifecycle
sushanb added a commit that referenced this pull request Jul 24, 2026
Bundles four related changes for the sessionz working branch:

1) 1x heartbeat multiplier (was 3x). resetHeartbeatDeadline and
   handleSessionParameters now compute `now + interval` instead of
   `now + 3*interval`. Matches java-bigtable's SessionImpl.java:440
   (nextHeartbeat = clock.instant().plus(heartbeatInterval)). Under
   healthy operation nothing changes — each frame's reset fires before
   the timer wakes. Only sessions where the server genuinely goes
   silent for one interval trip the watchdog.

2) heartBeatLoop cleanup:
   - Delete `active := 1 // multiplex=1; kept as %d so a future >1
     stays greppable` code smell (variable existed only for its
     self-documenting comment).
   - lastFrameAge = interval - remaining (was 3*interval - remaining)
     to match the new 1x deadline.
   - Debugf/recordEvent format strings drop the in_flight=%d field
     that was carrying the constant 1.

3) Vet fixes matching PR googleapis#20213's CI signal:
   - virtRpc → virtRPC (initialism convention).
   - runVRpcCapture and runInvoke: ctx moves to first parameter per
     Go convention. Updated all 5 + 5 callers in the test file.

4) SESSION_SPEC.md #7: update the "Deadline = 3 × heartbeatInterval"
   bullet to reflect the new 1x semantics and default interval.

Tests:
- TestHandleSessionParameters_UpdatesIntervalAndDeadline: expect
  deadline ~= before+interval (1x) instead of before+3*interval.
- TestHeartBeatLoop_HeartbeatsKeepInflightVRPCAlive: seed deadline
  at now+30ms (1x) instead of now+90ms (was 3x).
sushanb added a commit that referenced this pull request Jul 27, 2026
…Loop, heartBeatLoop)

Third and final PR in the Session core stack. Adds the lifecycle
orchestration that drives a Session from Start through teardown, plus
the readLoop that dispatches server frames to the vRPC handlers landed
in bigtable-session-vrpc.

Stacks on bigtable-session-vrpc; deletes the minimal ForceClose stub
that PR shipped, replacing it with the full lifecycle-shaped body.

New file: session_lifecycle.go (~640 LOC)
- Session.Start(ctx, OpenSessionRequest) — transitions New→Starting,
  Sends the OpenSession frame, fires onStart, spawns readLoop +
  heartBeatLoop. Wraps a failed Send as codes.Unavailable so retry
  plumbing treats pre-wire OpenSession loss the same as any other
  transport-side loss.
- ForceClose — full body: transitionTo(Closed), setCloseReason,
  notifyClosing (once), cancelActiveRPCs, signalQuiescent, notifyClosed.
- Close(ctx, CloseSessionRequest) — graceful drain: Ready→Closing,
  waits on quiescent, sends CloseSession, transitions to
  WaitServerClose, arms the pool's stuck-session sweep to eventually
  ForceClose if the server never confirms.
- notifyClosing / notifyClosed — once-guarded hook dispatchers with
  the strict onClosing-precedes-onClose ordering enforced.
- readLoop(ctx) — Recv-loop that dispatches every SessionResponse
  variant via handleSessionResponse, drives handleClose on stream
  termination, records msgsRecv counters + resets heartbeat deadline
  on every recognized frame.
- handleSessionResponse — dispatch switch to
  handleOpenSession / handleVRPCResponse / handleErrorResponse /
  handleSessionParameters / handleGoAway / handleSessionRefreshConfig.
  Heartbeat frames update the deadline via resetHeartbeatDeadline; the
  unknown-payload branch records a debug tag but doesn't reset the
  deadline (so a misbehaving server can't keep the watchdog satisfied
  with junk).
- handleOpenSession — Starting→Ready transition, PeerInfo extract
  from the bidi header (synchronous, matches Java's onHeaders
  synchrony), fires onActive.
- handleGoAway / handleClose / handleErrorResponse / handleSessionParameters
  / handleSessionRefreshConfig — protocol-level handlers.
- heartBeatLoop — Timer + heartbeatWake reactive-wake pair. Only
  enforces the deadline while a vRPC is in flight (idle sessions
  legitimately receive no server heartbeats). See SESSION_SPEC.md #7.
- peerInfoExtracter — parses the bigtable-peer-info header, stamps
  s.peerInfo atomically before onActive fires.
- closeReasonLabel / closeReasonToCause — CloseSessionRequest.Reason
  → string / sentinel error mapping for close-reason attribution.

New file: session_lifecycle_test.go (~660 LOC) — 30+ tests covering
Start, ForceClose, Close, readLoop, handleSessionResponse dispatch,
handleOpenSession + peerInfo parsing, handleGoAway, handleClose,
handleErrorResponse (rpc_id=0 harmlessly drops via routeVRPCFrame
guards), heartBeatLoop (reactive wake, idle-gate, missed-heartbeat
ForceClose).

Edits to session_vrpc.go
- Delete the minimal ForceClose stub introduced in the prior PR —
  the full body lives in session_lifecycle.go now.

Edits to session_test.go
- Add hookCounts helper (start/active/close callback counters).
- Add setSlotForTest helper (seed the in-flight slot from tests).

Stack:
- googleapis#20211 — Session debug surface
- googleapis#20213 — Session vRPC dispatch + slot lifecycle
- This PR — Session lifecycle
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