Kaynağa Gözat

Delay closing until the next loop tick (#1326)

Motivation:

When the idle handler determines that the channel needs to be closed
(becuase the connection is no longer required) it does so on the current
event loop tick. Closing immediately means that some events which are
already scheduled to run on the current tick may be dropped unexpectedly.

Modifications:

- Execute the channel close on the next event-loop tick.
- Fixup a test which now requires an extra loop `run()`.

Result:

Shutdown is a little more graceful.
George Barnett 4 yıl önce
ebeveyn
işleme
c43be58103

+ 6 - 2
Sources/GRPC/GRPCIdleHandler.swift

@@ -157,8 +157,12 @@ internal final class GRPCIdleHandler: ChannelInboundHandler {
     }
 
     // Close the channel, if necessary.
-    if operations.shouldCloseChannel {
-      self.context?.close(mode: .all, promise: nil)
+    if operations.shouldCloseChannel, let context = self.context {
+      // Close on the next event-loop tick so we don't drop any events which are
+      // currently being processed.
+      context.eventLoop.execute {
+        context.close(mode: .all, promise: nil)
+      }
     }
   }
 

+ 1 - 0
Tests/GRPCTests/ConnectionManagerTests.swift

@@ -800,6 +800,7 @@ extension ConnectionManagerTests {
         payload: .goAway(lastStreamID: 1, errorCode: .noError, opaqueData: nil)
       )
       XCTAssertNoThrow(try channel.writeInbound(goAway))
+      self.loop.run()
     }
 
     self.loop.run()