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
Use System.IO.Pipelines for sending #303
Conversation
77e074f
to
d5b2615
Compare
I just started a long running test with JS publisher and consumer just to make sure there are no regressions. |
It is also useful and simplifies a lot just to use a BoundedChannel instead of That should simplify the CommandWriter code quite a bit, and connection exceptions can be bubbled up in the WriteLoop by completing the ChannelWriter with an exception for example. With the Channel, you can also in many/most cases avoid the async state machine when the Channel isn't full, by doing a TryWrite and only falling down to WriteAsync when that fails (the bounded channel is full and waiting for the Write loop to pull stuff off it first). That makes PublishAsync very cheap for the cases where the Pipeline buffer can keep up with the channel ingress. |
We could, but we would have to introduce another layer of memory and copying. Right now Command Writer is writing directly to the Pipe Writer's buffers, which are the same buffers that get flushed to the Pipe Reader and sent on the wire. Access to the Pipe Writer's buffers must be serialized. Worse case scenario for adding a |
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleblloyd@gmail.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleblloyd@gmail.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
a621872
to
369df0d
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.
Looks good at first glance. Important thing is the bit about pipe reader try-finally thing. Others are nits.
src/NATS.Client.Core/Internal/NatsPipeliningWriteProtocolProcessor.cs
Outdated
Show resolved
Hide resolved
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
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.
Still need to look at some things closer but wanted to leave what feedback I have
I'm still reviewing but wanted to try to add some flavor to all of this;
At this point I probably -should- pull down the PR and look, How does SemaphoreSlim help here? Main reason I ask is that it does not, AFAIK, have FIFO behavior as a guarantee.
It's possible that it was being suggested, rather than use a Getting more specific, as a semi-contrived example, [0] - In fact, I have done so on more than one occasion to 'gate' [1] - I've seen this myself, where |
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
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.
LGTM
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Signed-off-by: Caleb Lloyd <caleb@synadia.com>
Refactors command sending to use
System.IO.Pipelines
PublishAsync
There is a possibility that the Connection drops before the Pipe Reader is read and actually sends the bytes on the Network. If so, the bytes remain in the Pipe Reader and will be sent if the Connection reconnects. So the only way to ensure that the bytes were actually sent to the server is to perform a round-trip with
PingAsync
. I believe that this behavior is similar to the Go client.Performance
Performance is similar to
WaitUntilSent=false
but a little better due to some reduced allocationsBefore:
After
Backwards Compatibility
I aimed to make the changes as Backward Compatible as possible, but there are some considerations:
NatsPubOpts.WaitUntilSent
andNatsPubOpts.ErrorHandler
have been marked as ObsoleteNatsPubOpts
NatsPubOpts
, such as a per-publishCommandTimeout
override. So we probably shouldn't get rid of itCommandTimeout
was lowered from 1 minute by default to 5 seconds. It is used to throw a Timeout exception if anything in the path of sending the command times out, including:AckOpts
were not in a format that matchedNatsPubOpts
andNatsSubOpts
so I standardized those and got rid ofWaitUntilSent