grpc/grpc-dotnet

Calling GetStatus on AsyncClientStreaming method sometimes throws an exception

namigop opened this issue · 2 comments

What version of gRPC and what language are you using?

Grpc.Net.Client 2.57.0, F#

What operating system (Linux, Windows,...) and version?

MacOS

What runtime / compiler are you using (e.g. .NET Core SDK version dotnet --info)

.NET 8

What did you do?

In pseudocode,

  1. Call a method that returns an AsyncClientStreamingCall<Req,Resp>.
  2. Call RequestStream.WriteAsync and await it
  3. Call RequestStream.CompleteAsync and await it
  4. Call AsyncClientStreamingCall.GetStatus(). <-- this call sometimes throws an exception
  5. If an exception is thrown, Retry the call to GetStatus. <- this will now succeed

What did you expect to see?

in Step 4, I expected the call to GetStatus to succeed everytime since the call to CompleteAsync was successful

What did you see instead?

in Step 4, an exception was thrown. Please see the GIF below

ClientStreamingError

Some logs from the tool

INFO: Call to ClientStreamWriter.Write done. Elapsed 27.7112 msec
INFO: Call to ClientStreamWriter.Complete done. Elapsed 1.6599 msec
INFO: Call to ResponseHeadersAsync done. Elapsed 9668.1523 msec
ERROR: Call to GetStatus failed. Elapsed 70.0057 msec
ERROR: System.InvalidOperationException: Unable to get the status because the call is not complete.
   at Grpc.Net.Client.Internal.GrpcCall`2.GetStatus()
   at Grpc.Net.Client.Internal.Retry.RetryCallBase`2.GetStatus()
   at Grpc.Net.Client.Internal.HttpClientCallInvoker.Callbacks`2.<>c.<.cctor>b__4_1(Object state)
   at Grpc.Core.AsyncCallState.GetStatus()
   at Grpc.Core.AsyncClientStreamingCall`2.GetStatus()
   at <StartupCode$Tefin-Grpc>.$CallInterceptor.clo@86-8.Invoke(Unit unitVar)
   at Tefin.Core.TimeIt.runActionWithReturnValue[T](FSharpFunc`2 action, FSharpOption`1 onSuccess, FSharpOption`1 onError) in /Users/erik.araojo/Work/Source/DotNet/FintX/FintX/source/Tefin.Core/TimeIt.fs:line 28
INFO: Call to GetStatus done. Elapsed 1.2168 msec
INFO: Call to GetTrailers done. Elapsed 0.7122 msec
INFO: Call to ResponseAsync done. Elapsed 9810.9315 msec
INFO: Invoking ClientStream @ http://localhost:5000
INFO: Call to ClientStreamWriter.Write done. Elapsed 2.9995 msec
INFO: Call to ClientStreamWriter.Complete done. Elapsed 0.0492 msec
INFO: Call to ResponseHeadersAsync done. Elapsed 11288.2172 msec
INFO: Call to GetStatus done. Elapsed 0.0053 msec
INFO: Call to GetTrailers done. Elapsed 0.0232 msec
INFO: Call to ResponseAsync done. Elapsed 11315.9338 msec

Make sure you include information that can help us debug (full error message, exception listing, stack trace, logs).

See TROUBLESHOOTING.md for how to diagnose problems better.

Anything else we should know about your project / environment?

I'm creating a test bench tool for gRPC. Same as the WcfClient for WCF
https://github.com/namigop/FintX

CompleteAsync just ends the request stream. Awaiting it doesn't mean the server has finished the call (it could be busy doing work and not waiting for the next message at that point in time) and sent a status to the client (there is latency between server and client).

You need to await the response from the client stream to guarantee the call is completed.

Thank you for the clarification @JamesNK. I updated my code to call GetStatus only after awaiting the response from the client stream and the error is now gone. On another note, I would greatly appreciate it if you could try out FintX! I already got the Unary, ServerStreaming, ClientStreaming and DuplexStreaming calls working.

https://github.com/namigop/FintX