소스 검색

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 년 전
부모
커밋
c43be58103
2개의 변경된 파일7개의 추가작업 그리고 2개의 파일을 삭제
  1. 6 2
      Sources/GRPC/GRPCIdleHandler.swift
  2. 1 0
      Tests/GRPCTests/ConnectionManagerTests.swift

+ 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()