Эх сурвалжийг харах

Reset go away state (#49)

Motivation:

The pick first load balancer keeps track of whether the current
subchannel is going away. This is done so that if there isn't yet a
subchannel to roll over too it won't be offered up when the GRPCChannel
asks for a subchannel. However, this state wasn't reset in enough places
within the state machine.

Modifications:

- Reset the is-going-away state when updating the current subchannel and
when the current subchannel becomes idle

Result:

Resolves #40
George Barnett 11 сар өмнө
parent
commit
289c0bc09e

+ 7 - 0
Sources/GRPCNIOTransportCore/Client/Connection/LoadBalancers/PickFirstLoadBalancer.swift

@@ -328,6 +328,7 @@ extension PickFirstLoadBalancer.State.Active {
       if self.connectivityState == .idle {
         // Current subchannel is idle and we have a new endpoint, move straight to the new
         // subchannel.
+        self.isCurrentGoingAway = false
         self.current = newSubchannel
         self.parked[current.id] = current
         onUpdateEndpoint = .connect(newSubchannel, close: current)
@@ -345,10 +346,12 @@ extension PickFirstLoadBalancer.State.Active {
       onUpdateEndpoint = .connect(newSubchannel, close: next)
 
     case (.none, .none):
+      self.isCurrentGoingAway = false
       self.current = newSubchannel
       onUpdateEndpoint = .connect(newSubchannel, close: nil)
 
     case (.none, .some(let next)):
+      self.isCurrentGoingAway = false
       self.current = newSubchannel
       self.next = nil
       self.parked[next.id] = next
@@ -368,6 +371,10 @@ extension PickFirstLoadBalancer.State.Active {
       if connectivityState == self.connectivityState {
         onUpdate = .none
       } else {
+        // If the subchannel was going away and became idle then it went away.
+        if connectivityState == .idle {
+          self.isCurrentGoingAway = false
+        }
         self.connectivityState = connectivityState
         onUpdate = .publishStateChange(connectivityState)
       }

+ 2 - 0
Tests/GRPCNIOTransportCoreTests/Client/Connection/LoadBalancers/PickFirstLoadBalancerTests.swift

@@ -295,6 +295,7 @@ final class PickFirstLoadBalancerTests: XCTestCase {
       case .connectivityStateChanged(.ready):
         switch idleCount.value {
         case 1:
+          XCTAssertNotNil(context.loadBalancer.pickSubchannel())
           // Must be connected to server 1, send a GOAWAY frame.
           let channel = context.servers[0].server.clients.first!
           let goAway = HTTP2Frame(
@@ -307,6 +308,7 @@ final class PickFirstLoadBalancerTests: XCTestCase {
           // Must only be connected to server 2 now.
           XCTAssertEqual(context.servers[0].server.clients.count, 0)
           XCTAssertEqual(context.servers[1].server.clients.count, 1)
+          XCTAssertNotNil(context.loadBalancer.pickSubchannel())
           context.loadBalancer.close()
 
         default: