8000 Update to mainline BestHTTP by colinrgodsey · Pull Request #9 · doctorseus/grpc-dotnet-unity · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Update to mainline BestHTTP #9

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

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

colinrgodsey
Copy link
@colinrgodsey colinrgodsey commented Mar 21, 2024

BestHTTP/2 has been discontinued, and the support has been folded into mainline BestHTTP. The APIs are a little different, so had to upgrade them, but its working fine for us so far after a decent amount of torture testing.

  • Will do a bit more testing
  • Docs probably need to be updated, not sure if you'd like us to do that.

// but in any case we want to close the stream to indicate to grpc that we are done
else
{
incomingDataStream.Close();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can't close the data stream as part of concluding the request, as the download stream may still be draining in the background. so the download process is responsible for closing the stream on the happy path now. any exception paths can still close the stream with an exception though

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

except in the case of a trailers only response where we get no DATA, that will still close the stream

{
if (m_Exception != null)
throw m_Exception;

// Either we have data to read, or we got flushed (e.g. stream got closed)
// or we are in non blocking read mode.
return Length >= count && m_Flushed || m_Closed || NonBlockingRead;
return m_Buffer.Count > 0 || m_Flushed || m_Closed || NonBlockingRead;
Copy link
Author
@colinrgodsey colinrgodsey May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gRPC still expects the standard .NET stream semantics of: only returning from a Read with at least 1 byte of data, unless we reached EOF/EOS (in our case, flush/close), then we can return 0 or negatives. Returning partial reads (n < count) is still fine and handled appropriately in grpc.net.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and it ultimately doesnt matter which side holds the buffer, but just felt better to me to drain this man-in-the-middle stream as fast as possible

}

public override long Length => m_Buffer.Count;
// Avoid sending content-length=0 (EOF) by using -2 for chunked encoding.
public override long Length => -2;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can leave this at -2 and Best HTTP will just stay in streaming/unbounded data mode, and will treat a -1 from Read as the EOF/EOS


namespace GRPC.NET
{
public class PushPullStream : Stream
public class PushPullStream : UploadStreamBase
Copy link
Author
@colinrgodsey colinrgodsey May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new base class for the uploader which handles receiving the thread signal on its own (although we still need to call it in Flush)

else
{
// The DownloadContentStream does not block, so wait a bit.
await Task.Delay(ASYNC_READ_WAIT_MS, cancellationToken);
Copy link
Author
@colinrgodsey colinrgodsey May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

never happy about polling delays, but it is what it is. havent seen any other available notice/signal pattern for downloads in Best HTTP, but I may have missed it.

incomingDataStream.Write(fragment, 0, length);
incomingDataStream.Flush();
return true;
try
8000 Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new download streaming pattern:

  1. drain all available download at the time of this callback
  2. if the stream isn't done, kick off a Task and poll for new data until complete. The new "detatched" pattern will hold resources open until we finish draining and close the stream


for (; readLength < count && Length > 0 && m_Buffer.Count > 0; readLength++)
{
for (; readLength < count && m_Buffer.Count > 0; readLength++)
buffer[readLength] = m_Buffer.Dequeue();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

offset needs to be added here:

buffer[offset+readLength] = ...

just got bit by that bug today...

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @colinrgodsey, thanks for also finding this bug. :-) I assume this happens for larger messages or how could we trigger this with a new testcase? For the initial version I tried to add a test-case for each bug I encountered.
Personally I only used high frequent short messages in production and testing until now.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

definitely a good idea keeping test cases for encountered bugs! not sure what exact internal behavior triggered this, but it did happen with a message that was larger than 128KB. i do fear the exact issue may have had to with some concurrent behavior (triggering a read on an existing buffer that hasnt been completely consumed/drained yet). although it was rather consistent in our case with this exact payload.

Use offset in `Read`
@colinrgodsey
Copy link
Author

@doctorseus we've had this in production for a quite a while now with no issues. think its all looking solid

< 6738 /div>
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.

2 participants
0