Browse Source

Allow end stream to be dropped in the async server handler (#1323)

Motivation:

The async server handler throws an error if the end-of-stream received
from the client is dropped. The end-of-stream will only be dropped if
the request stream has already been finished. This happens in a few
cases: either end-of-stream has already been received, or as a side
effect of the task running the user handler completing.

The latter case is possible of the user handler does not wait for end of
stream (if it encounters an error, for example). This happened
periodically in some tests as a result of the user handler completing
and receiving end-stream racing.

Modifications:

- Tolerate dropping end stream in the async server handler.

Result:

Fewer flakey tests.
George Barnett 4 years ago
parent
commit
a6d3157dee
1 changed files with 3 additions and 5 deletions
  1. 3 5
      Sources/GRPC/AsyncAwaitSupport/GRPCAsyncServerHandler.swift

+ 3 - 5
Sources/GRPC/AsyncAwaitSupport/GRPCAsyncServerHandler.swift

@@ -492,11 +492,9 @@ internal final class AsyncServerHandler<
       case .accepted(queueDepth: _):
       case .accepted(queueDepth: _):
         break
         break
       case .dropped:
       case .dropped:
-        /// If we are in the `.active` state then we have yet to encounter an error. Therefore
-        /// if the request stream source has already terminated then it must have been the result of
-        /// receiving `.end`. Therefore this `.end` must have been sent by the client after it
-        /// already sent `.end`, which is a protocol violation.
-        self.handleError(GRPCError.ProtocolViolation("Message duplicate end of stream"))
+        // The task executing the user handler will finish the request stream source after the
+        // user handler completes. If that's the case we will drop the end-of-stream here.
+        break
       }
       }
     case .completed:
     case .completed:
       // We received a message but we're already done: this may happen if we terminate the RPC
       // We received a message but we're already done: this may happen if we terminate the RPC