-
Notifications
You must be signed in to change notification settings - Fork 974
chore: add backed reader, writer and pipe implementation #19147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
9dd9c4a
to
3223bf9
Compare
d2ee08d
to
27da7ef
Compare
16abe05
to
dde9516
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not done with my review, but taking a break and wanted to send you comments so far.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another batch of comments.
I haven't really looked at BackedPipe yet, but I think maybe it would be better to wait for the comments I've made so far to be resolved.
7468299
to
b2188f9
Compare
45558ec
to
064514e
Compare
… to block on errors
…being closed/reconnected race conditions
separate channels for writer/reader errors moved to an interface for reconnection coordination logic for closing a pipe
…etter error tracking
95dc01a
to
85c505d
Compare
|
||
// Update the generation on reader and writer for error reporting | ||
bp.reader.SetGeneration(bp.connGen) | ||
bp.writer.SetGeneration(bp.connGen) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should set both of these during the Reconnect
calls. With it like this, the Reconnect
can finish and unblock reads/writes, which could error before you set the generation here, and then get ignored, hanging the pipe.
// Get current writer sequence number to send to remote | ||
writerSeqNum := bp.writer.SequenceNum() | ||
|
||
conn, readerSeqNum, err := bp.reconnector.Reconnect(bp.ctx, writerSeqNum) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is backwards. You need to send the reader sequence number to the remote. The point of the sequence numbers is to inform the other side how much data we successfully read, so that it can replay from that number.
func NewBackedPipe(ctx context.Context, reconnector Reconnector) *BackedPipe { | ||
pipeCtx, cancel := context.WithCancel(ctx) | ||
|
||
errorChan := make(chan ErrorEvent, 10) // Buffered for async error reporting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the deal with 10? Like, why is that the right size for this buffer?
In general, I'd encourage you to consider anything other than 0 or 1 to be suspicious. There are legit uses for other numbers, but generally only if we are "buffering" to smooth out spiky usage.
}() | ||
|
||
// Wait for read to start | ||
testutil.RequireReceive(ctx, t, readStarted) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
readStarted
doesn't actually verify that the Read
call has started, since it happens on line 121 and read doesn't happen until line 123. As such it doesn't really add anything to this test and should get removed.
// Read is still blocked, which is what we want | ||
return !br.Connected() | ||
} | ||
}, testutil.WaitShort, testutil.IntervalMedium) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why this is wrapped in Eventually
--- the reader has never connected at this point, so br.Connected() == true
should be a test failure, not a retry. The other branch of the select is also a test failure.
Fixes: #18101
This PR introduces a new
backedpipe
package that provides reliable bidirectional byte streams over unreliable network connections. The implementation includes:BackedPipe
: Orchestrates a reader and writer to provide transparent reconnection and data replayBackedReader
: Handles reading with automatic reconnection, blocking reads when disconnectedBackedWriter
: Maintains a ring buffer of recent writes for replay during reconnectionRingBuffer
: Efficient circular buffer implementation for storing dataThe package enables resilient connections by tracking sequence numbers and replaying missed data after reconnection. It handles connection failures gracefully, automatically reconnecting and resuming data transfer from the appropriate point.