drpcstream: add per-stream send-window credit primitive#70
Merged
Conversation
suj-krishnan
force-pushed
the
sujatha/flow-control-window-update
branch
from
July 13, 2026 07:00
513c137 to
14e3978
Compare
suj-krishnan
force-pushed
the
sujatha/flow-control-send-window
branch
2 times, most recently
from
July 13, 2026 07:06
a4ad9e8 to
6ff7baf
Compare
suj-krishnan
force-pushed
the
sujatha/flow-control-window-update
branch
from
July 13, 2026 08:41
14e3978 to
4273044
Compare
suj-krishnan
force-pushed
the
sujatha/flow-control-send-window
branch
3 times, most recently
from
July 13, 2026 08:55
9c3bc23 to
efc77b4
Compare
suj-krishnan
force-pushed
the
sujatha/flow-control-window-update
branch
from
July 13, 2026 08:59
4273044 to
9c0b23b
Compare
suj-krishnan
force-pushed
the
sujatha/flow-control-send-window
branch
from
July 13, 2026 08:59
efc77b4 to
d88576b
Compare
Define the KindWindowUpdate control frame that carries a flow-control credit grant: a varint byte delta in the body, for the stream named by the frame's stream id. Add WindowUpdateFrame/ParseWindowUpdate helpers to build and read it. Stream id 0 is reserved for a possible future connection-level window and is unused in v1. The control bit marks the frame as out-of-band signaling, so it is emitted without blocking on data backpressure. It is not relied on for backward compatibility: an unknown control frame is only dropped after packet assembly, so it is not safely ignorable on an active stream. Instead, grants are only ever sent once flow control is active cluster-wide, so a peer that predates flow control never receives one. ParseWindowUpdate enforces the whole v1 wire contract in one place, since these frames are intercepted before packet assembly and its message-id checks: it accepts only a self-contained control frame (Control and Done set) naming a real stream (id != 0) with a positive delta and no trailing bytes. A non-conforming frame yields ok=false and is dropped by the caller, so a reserved stream-0 update from a future peer is ignored rather than mishandled. This is dormant scaffolding for the flow-control work: nothing emits or acts on the frame yet. Co-Authored-By: roachdev-claude <roachdev-claude-bot@cockroachlabs.com>
suj-krishnan
force-pushed
the
sujatha/flow-control-window-update
branch
from
July 13, 2026 09:17
9c0b23b to
5c858e3
Compare
suj-krishnan
force-pushed
the
sujatha/flow-control-send-window
branch
7 times, most recently
from
July 13, 2026 12:29
b1f5883 to
4d08d0b
Compare
suj-krishnan
marked this pull request as ready for review
July 13, 2026 12:50
shubhamdhama
requested changes
Jul 14, 2026
| // now. acquire spends credit (blocking until enough is available), grant adds | ||
| // credit, and close terminates the window. | ||
| // | ||
| // avail is a signed int64; |
Comment on lines
+131
to
+132
| close(w.notify) | ||
| w.notify = make(chan struct{}) |
There was a problem hiding this comment.
Employ something like
Lines 76 to 85 in cbabd21
Author
There was a problem hiding this comment.
You mean, add the check so we don't allocate when there are no waiters? I didn't keep it because grants are not as frequent (we coalesce and grant only for every 1 MB or so) - keeping a blocked counter and updating in every case didn't seem worth it. (The mux_writer logic is clearly in the hot path and needs it).
I will use a nil check on the channel instead to save on the allocation.
suj-krishnan
force-pushed
the
sujatha/flow-control-send-window
branch
from
July 15, 2026 11:03
4d08d0b to
deefd7b
Compare
shubhamdhama
self-requested a review
July 15, 2026 14:44
shubhamdhama
approved these changes
Jul 15, 2026
Add sendWindow, the per-stream flow-control credit balance on the sender. acquire spends credit, blocking until enough is available; grant adds credit; close terminates the window. acquire returns early on close (with the close error) or context cancellation (with ctx.Err()), consuming no credit in either case; both are checked before any debit, so a canceled context never consumes credit or lets a frame proceed even when credit is available. Grants are no-revoke: grant takes an unsigned delta (the wire type), so a grant can only ever raise the balance, and the addition saturates at math.MaxInt64 so a large or malicious delta can never wrap it negative. The balance is a signed int64; acquire never drives it below zero, but the enablement layer may debit credit for bytes sent before flow control begins enforcing, leaving it negative, in which case acquire blocks until grants restore it. This is the primitive only -- it is not yet wired into the stream write path (that gate comes in a later commit). Co-Authored-By: roachdev-claude <roachdev-claude-bot@cockroachlabs.com>
suj-krishnan
force-pushed
the
sujatha/flow-control-send-window
branch
from
July 16, 2026 09:08
deefd7b to
af4331b
Compare
Author
|
TFTR @shubhamdhama! |
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.
Adds
sendWindow, the per-stream flow-control credit balance on the sender:acquire(ctx, n)— spends credit, blocking until enough is available; interruptible by both context cancellation andclose, consuming no credit when it bails.grant(n)— strictly additive (no-revoke); wakes a parked acquirer.close(err)— terminates the window, waking all waiters with the error.A grant only ever adds credit; the receiver never takes back credit it has already issued. The balance is a signed
int64: the flow control enablement design (pre-armed accounting, see the design doc) has the sender debit bytes it sends before flow control begins enforcing, which can leave the balance negative — a stream then repays that deficit from incoming grants before its next message.acquireblocks whenever available credit is below what the next frame needs, negative balances included.Scope: the primitive only. It is not yet wired into the stream write path.
Tests: immediate acquire, grants accumulate, blocks-until-grant, context-cancel wake, close wake, acquire-after-close. All pass under
-race.