Skip to content

drpcstream,drpcmanager: enable per-stream flow control (grant-on-consume) - #89

Open
suj-krishnan wants to merge 1 commit into
mainfrom
sujatha/flow-control-consume-enable
Open

drpcstream,drpcmanager: enable per-stream flow control (grant-on-consume)#89
suj-krishnan wants to merge 1 commit into
mainfrom
sujatha/flow-control-consume-enable

Conversation

@suj-krishnan

@suj-krishnan suj-krishnan commented Jul 28, 2026

Copy link
Copy Markdown

Installs per-stream flow-control windows from an internal FlowControl option and proves the mechanism end to end. This is the enablement layer only; the message-boundary overdraft that makes it deadlock-free for multi-frame and larger-than-window messages is stacked on top in #92.

Installs the per-stream windows when FlowControl is set: the send window seeded with StreamWindow credit and watching the send signal for termination; the receive window returning consumed-byte credit coalesced at GrantThreshold.

Enablement is internal-only (merge safety). The option lives in internal/drpcopts (SetStreamFlowControl), not on the public drpcstream.Options — so a consumer bumping the drpc dependency mid-implementation cannot enable flow control: no public API reaches it. Promotion to a public option is a later, deliberate change.

Validation at the installation site. An invalid configuration resorts to mutually-consistent defaults (and logs the override) instead of failing the stream:

  • StreamWindow and GrantThreshold must be positive;
  • a non-positive SplitSize uses SplitData's 64 KiB default as the frame size;
  • GrantThreshold + frame ≤ StreamWindow — the liveness guarantee for grant coalescing. With G = GrantThreshold, W = StreamWindow, F = frame: once the receive side has consumed more than W − F of the window, the sender has < F credit left and halts; if G > W − F, the receiver cannot emit a grant to unblock it either — deadlock. Requiring G ≤ W − F prevents that.

End to end. drpcmanager tests move more data than the window holds over a real net.Pipe, so the transfer only completes if consume-driven grants flow back across the connection; context cancellation wakes a sender parked on credit through the production manageStream path; and a default-configuration (flow-control-off) connection never puts a KindWindowUpdate on the wire.

@suj-krishnan
suj-krishnan force-pushed the sujatha/flow-control-recv-window-consume branch 4 times, most recently from 12ae0a8 to 5a99ec2 Compare July 29, 2026 08:47
Base automatically changed from sujatha/flow-control-recv-window-consume to main July 29, 2026 08:49
@suj-krishnan
suj-krishnan force-pushed the sujatha/flow-control-consume-enable branch 5 times, most recently from b7f5aee to eaa5f1e Compare July 29, 2026 14:56
…option

Add drpcopts.FlowControl (Enabled, StreamWindow, GrantThreshold) and
install the per-stream windows at stream creation when it is set: the
send window seeded with StreamWindow credit and watching the send signal
for termination, and the receive window returning consumed-byte credit
coalesced at GrantThreshold.

Enablement is internal-only for merge safety: the option lives in
internal/drpcopts, not on the public drpcstream.Options, so a consumer
bumping the dependency cannot enable flow control before the deliberate
promotion to a public option.

The installation site normalizes the configuration rather than failing.
The frame size follows SplitData: zero uses the 64 KiB default, and a
negative SplitSize means unbounded frames, which carry no per-frame
bound. A valid config needs positive sizes and, for bounded frames,
GrantThreshold plus one frame fitting in StreamWindow -- so credit
withheld by coalescing cannot strand the sender below the next frame's
cost. Anything that cannot make progress resorts to
FlowControl.SetDefaults and logs the override, so a misconfiguration
degrades to a working stream instead of crashing a process that embeds
drpc.

End-to-end tests in drpcmanager prove the mechanism over a real
connection:

  - Managers on both ends of a net.Pipe with flow control enabled move
    four window-sized messages -- twice the stream window -- so the
    transfer only completes if consume-driven grants flow back across the
    connection.
  - Context cancellation wakes a sender parked on credit via the
    production path: manageStream sees the cancellation and terminates,
    setting sigs.send, the send window's done signal.
  - Tripwire: a default-configuration connection never puts a
    KindWindowUpdate on the wire, so flow control cannot be enabled by
    accident.

Co-Authored-By: roachdev-claude <roachdev-claude-bot@cockroachlabs.com>
@suj-krishnan
suj-krishnan marked this pull request as draft July 30, 2026 02:21
@suj-krishnan
suj-krishnan force-pushed the sujatha/flow-control-consume-enable branch from eaa5f1e to 88c548d Compare July 30, 2026 04:10
@suj-krishnan
suj-krishnan marked this pull request as ready for review August 3, 2026 05:19
@suj-krishnan
suj-krishnan force-pushed the sujatha/flow-control-consume-enable branch from 88c548d to 63ac053 Compare August 3, 2026 05:34
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