Open piotrkowalczuk opened 6 days ago
Hi Piotr, thanks for filing this and trying out the alpha release!
We are certainly aware of some bugs but it's a bit surprising that this simple setup doesn't work...
Describe the bug
I'm new to Swift so I'm aware that it might be something on my end. Nevertheless, I will try my luck and report it as bug.
I have a very simple setup where I make an attempt to make a call stright from main struct of iOS app. Without luck, I'm getting
unavailable: "channel isn't ready"
.
To clarify, is the server also running within your iOS app? I'd like to understand the setup better so I can reproduce it locally. As you noted there are no logs here: there are two logging systems in Swift (swift-log and OSLog), so we're currently evaluating how best to handle observability, which obviously makes things harder to debug at the moment.
GRPC_TRACE=all GRPC_VERBOSITY=DEBUG GODEBUG=http2debug=1 GRPC_GO_LOG_VERBOSITY_LEVEL=99 GRPC_GO_LOG_SEVERITY_LEVEL=info
For what it's worth: none of these env variables will be used.
Changing to
NIOTS
do not help,print("2")
is never reached:let transport = try HTTP2ClientTransport.TransportServices( target: .ipv4(host: "127.0.0.1", port: 8081), config: .defaults(transportSecurity: .plaintext) ) print("1") try await transport.connect() print("2")
That's expected: connect()
is long running, it won't return until the transport has been shutdown (or the task has been cancelled). You snippet above using the task group and client is the correct way to run a client and its transport.
To clarify, is the server also running within your iOS app? I'd like to understand the setup better so I can reproduce it locally. As you noted there are no logs here: there are two logging systems in Swift (swift-log and OSLog), so we're currently evaluating how best to handle observability, which obviously makes things harder to debug at the moment.
The server is running on my localhost. It's a Go app.
A minimal setup that allows me to reproduce the issue:
import NIOTransportServices
import GRPCNIOTransportHTTP2
import MY_PACKGE
import Foundation
try await withThrowingDiscardingTaskGroup { group in
let client = GRPCClient(
transport: try .http2NIOPosix(
target: .ipv4(host: "127.0.0.1", port: 8081),
config: .defaults(transportSecurity: .plaintext)
)
)
group.addTask {
try await client.run()
}
defer {
client.beginGracefulShutdown()
}
let auth =
MY_CLIENT(
wrapping: client)
do {
let res = try await auth.MY_METHOD(
.with {
$0.userID = UUID().uuidString
})
print(res)
} catch {
print("error: \(error)")
}
}
// swift-tools-version: 6.0
import PackageDescription
let package = Package(
name: "debug",
platforms: [
.macOS(.v15),
],
products: [
.executable(name: "debug", targets: ["debug"])
],
dependencies: [
.package(path: "../my_package"),
],
targets: [
.executableTarget(
name: "debug",
dependencies: [
.product(name: "MY_PACKAGE", package: "my_package"),
]
),
]
)
.package(url: "https://github.com/grpc/grpc-swift-nio-transport.git", from: "1.0.0-alpha.1"),
.package(url: "https://github.com/grpc/grpc-swift.git", from: "2.0.0-alpha.1"),
.package(url: "https://github.com/grpc/grpc-swift-protobuf.git", from: "1.0.0-alpha.1"),
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.27.2"),
and it gives
swift run debug
Building for debugging...
[1/1] Write swift-version--58304C5D6DBC2206.txt
Build of product 'debug' complete! (2.61s)
error: unavailable: "channel isn't ready"
Okay, I just want to confirm your current setup because I think it's changed, you now have a Swift client running on the same machine as a Go server?
Yes the same machine.
I setup a Go server and used a Swift client and wasn't able to reproduce this.
However, what I did notice was that the Go server in the gRPC Go examples bound to an IPv6 address ("::1") – is your Go server also bound to an IPv6 address?
I have the same problem in my iOS project with version 2.0.0-alpha.1
func gRPCEvents() async throws {
let client = GRPCClient(
transport: try .http2NIOPosix(
target: .ipv4(host: "localhost", port: 6162),
config: .defaults(transportSecurity: .plaintext)
)
)
try await withThrowingDiscardingTaskGroup { group in
group.addTask {
try await client.run()
}
defer {
client.beginGracefulShutdown()
}
let service = EventsService_Client(wrapping: client)
let events = try await service
.allEvents(Google_Protobuf_Empty())
print(events.events.count)
}
}
I have my own server on my machine "localhost" with vapor and 1.23.1 grpc version.
However, what I did notice was that the Go server in the gRPC Go examples bound to an IPv6 address ("::1") – is your Go server also bound to an IPv6 address?
Changing the listener to bind to ip4 explicitly did not help.
I have the same problem in my iOS project with version 2.0.0-alpha.1
func gRPCEvents() async throws { let client = GRPCClient( transport: try .http2NIOPosix( target: .ipv4(host: "localhost", port: 6162), config: .defaults(transportSecurity: .plaintext) ) ) try await withThrowingDiscardingTaskGroup { group in group.addTask { try await client.run() } defer { client.beginGracefulShutdown() } let service = EventsService_Client(wrapping: client) let events = try await service .allEvents(Google_Protobuf_Empty()) print(events.events.count) } }
I have my own server on my machine "localhost" with vapor and 1.23.1 grpc version.
@jcalderita "localhost" isn't an IPv4 address, so this should fail.
If you change .ipv4(host: "localhost", port: 6162)
to .dns(host: "localhost", port: 6162)
the DNS name resolver will be used and should resolve "localhost" to "127.0.0.1" and "::1" and try connecting to both.
However, what I did notice was that the Go server in the gRPC Go examples bound to an IPv6 address ("::1") – is your Go server also bound to an IPv6 address?
Changing the listener to bind to ip4 explicitly did not help.
Could you provide a complete minimal example with a Go server and a Swift client? Ideally zipped up so I can download it and just run the client and server.
I have the same problem in my iOS project with version 2.0.0-alpha.1
func gRPCEvents() async throws { let client = GRPCClient( transport: try .http2NIOPosix( target: .ipv4(host: "localhost", port: 6162), config: .defaults(transportSecurity: .plaintext) ) ) try await withThrowingDiscardingTaskGroup { group in group.addTask { try await client.run() } defer { client.beginGracefulShutdown() } let service = EventsService_Client(wrapping: client) let events = try await service .allEvents(Google_Protobuf_Empty()) print(events.events.count) } }
I have my own server on my machine "localhost" with vapor and 1.23.1 grpc version.
@jcalderita "localhost" isn't an IPv4 address, so this should fail.
If you change
.ipv4(host: "localhost", port: 6162)
to.dns(host: "localhost", port: 6162)
the DNS name resolver will be used and should resolve "localhost" to "127.0.0.1" and "::1" and try connecting to both.
It works!!!! Thank you!!!
Describe the bug
I'm new to Swift so I'm aware that it might be something on my end. Nevertheless, I will try my luck and report it as bug.
I have a very simple setup where I make an attempt to make a call stright from main struct of iOS app. Without luck, I'm getting
unavailable: "channel isn't ready"
.URLRequest
grpc-swift:1.23.1
curl
grpcurl
grpc-swift:2.0.0-alpha.1
(both posix and niots)To reproduce
Steps to reproduce the bug you've found:
@main struct
constructor.Expected behaviour
Ideally the request should succeed. In bare minimum I would like to see some logs from the transport layer on the server side.
Additional information
Server
The Go server that runs on my localhost has various debug modes enabled.
Code
Changing to
NIOTS
do not help,print("2")
is never reached:Dependencies
Settings
protoc-gen-grpc-swift
installed from source from https://github.com/grpc/grpc-swift-protobuf that depends on
grpc-swift:2.0.0-alpha.1
.