diff --git a/Sources/GRPCNIOTransportCore/Client/Connection/LoadBalancers/PickFirstLoadBalancer.swift b/Sources/GRPCNIOTransportCore/Client/Connection/LoadBalancers/PickFirstLoadBalancer.swift index c0f1b6f..ff3d20a 100644 --- a/Sources/GRPCNIOTransportCore/Client/Connection/LoadBalancers/PickFirstLoadBalancer.swift +++ b/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) } diff --git a/Tests/GRPCNIOTransportCoreTests/Client/Connection/LoadBalancers/PickFirstLoadBalancerTests.swift b/Tests/GRPCNIOTransportCoreTests/Client/Connection/LoadBalancers/PickFirstLoadBalancerTests.swift index 493f989..1ffe195 100644 --- a/Tests/GRPCNIOTransportCoreTests/Client/Connection/LoadBalancers/PickFirstLoadBalancerTests.swift +++ b/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: