grpc-swift
grpc-swift copied to clipboard
Don't receive network error from rpc when airplane mode has been turned on
What are you trying to achieve?
I make a RPC unary call and handle callbacks from it:
let call = client.makeUnaryCall(path: method, request: request, responseType: Response.self)
call.response.whenSuccess {
print("Success \($0)")
}
call.response.whenFailure {
print("Failure \($0)")
}
Then I turn on the airplane mode on my iOS device and I expect to receive within failure callback the network connection error passed immediately, but nothing happens. Indeed, I will receive the error when call timeout limit elapses, it will happen in 60 sec.
Also, I set a connectivityStateDelegate in ClientConnection and define in my class its protocol methods like:
extension GRPCNetworkInvoker: ConnectivityStateDelegate {
public func connectivityStateDidChange(from oldState: ConnectivityState, to newState: ConnectivityState) {
print("oldState: \(oldState)")
print("newState: \(newState)")
print("connectivityStateDidChange")
}
public func connectionStartedQuiescing() {
print("connectionStartedQuiescing")
}
}
And there is nothing called when I trigger the airplane mode on iOS device.
What have you tried so far?
I create a grpc client properly as it's described in docs:
let group = PlatformSupport.makeEventLoopGroup(loopCount: 1, networkPreference: .best)
let channel = ClientConnection
.usingTLS(with: .makeClientDefault(compatibleWith: group), on: group)
.withConnectivityStateDelegate(self)
.withConnectionReestablishment(enabled: false)
.withCallStartBehavior(.fastFailure)
.connect(host: hostEndpoint)
What it comes to objc grpc library that I used to it before, my case works great. Objc Grpc lib has a GRPCResponseHandler protocol and func didClose(withTrailingMetadata trailingMetadata: [AnyHashable : Any]?, error: Error?) is invoked immediately with network connection error passed when the airplane mode has been turned on.
Why swift grpc does't support reachability trait under the hood and doesn't notify via rpc failure callback right away if no connection occurs or the network on iOS has been shut down?
grpc-swift doesn't handle airplane mode at the moment.
For iOS we should be using Network.framework, and from the docs it seems like we'd be notified about airplane mode being enabled via a NWPathMonitor where we'd see a new NWPath which is unavailable.
In the NIO world, it looks like nio-transport-services will fire a corresponding PathChanged event which we should be able to pick up (but currently don't).
So, NWPath is a part of private API?
It seems like at least we can take a needed property via NIO.
On my view, it should be useful feature in the future. Are you going to implement it in near future?
NWPath and NWPathMonitor are not private API.
In general, however, NIO and grpc-swift follows the Network.framework guidance to not immediately fail but instead to wait for completion. I’m a bit surprised that the fast-fail code isn’t causing us to fail quicker here, however.
Unfortunately, NWPathMonitor solution doesn't work as you described at the moment because path becomes unavailable even in scenarios where a user manually disables wi-fi, for example not turning airplane mode on