Skip to content

Commit e45f09f

Browse files
committed
Fix multi callback from stateUpdateHandler issue
1 parent f6edc9d commit e45f09f

File tree

2 files changed

+50
-30
lines changed

2 files changed

+50
-30
lines changed

Sources/OpenGraphShims/DebugClient.swift

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,51 @@
44

55
#if canImport(Darwin)
66
public import Foundation
7-
import Network
7+
public import Network
88

99
#if canImport(OpenGraphCxx_Private)
1010
public import OpenGraphCxx_Private.DebugServer
1111
#endif
1212

13+
public struct ConnectionUpdates: AsyncSequence {
14+
public typealias Element = NWConnection.State
15+
16+
private let stream: AsyncStream<NWConnection.State>
17+
18+
fileprivate init(stream: AsyncStream<NWConnection.State>) {
19+
self.stream = stream
20+
}
21+
22+
public func makeAsyncIterator() -> AsyncStream<NWConnection.State>.AsyncIterator {
23+
stream.makeAsyncIterator()
24+
}
25+
}
26+
1327
@_spi(Debug)
1428
public final class DebugClient {
1529
private var connection: NWConnection?
16-
private let queue = DispatchQueue(label: "opengraph.debugserver.client.queue")
30+
private let queue = DispatchQueue(label: "org.openswiftuiproject.opengraph.debugclient")
1731

18-
public func connect(to url: URL) async throws {
32+
public func connect(to url: URL) -> ConnectionUpdates {
1933
guard let host = url.host, let port = url.port else {
20-
throw ClientError.invalidURL
34+
return ConnectionUpdates(stream: AsyncStream { continuation in
35+
continuation.yield(.failed(NWError.posix(.EINVAL)))
36+
continuation.finish()
37+
})
2138
}
22-
2339
let nwHost = NWEndpoint.Host(host)
2440
let nwPort = NWEndpoint.Port(integerLiteral: UInt16(port))
25-
2641
connection = NWConnection(host: nwHost, port: nwPort, using: .tcp)
27-
28-
return try await withCheckedThrowingContinuation { continuation in
42+
let stream = AsyncStream<NWConnection.State> { continuation in
2943
connection?.stateUpdateHandler = { state in
30-
switch state {
31-
case .ready:
32-
continuation.resume()
33-
case let .failed(error):
34-
continuation.resume(throwing: error)
35-
case .cancelled:
36-
continuation.resume(throwing: ClientError.connectionCancelled)
37-
default:
38-
break
44+
continuation.yield(state)
45+
if case .cancelled = state {
46+
continuation.finish()
3947
}
4048
}
4149
connection?.start(queue: queue)
4250
}
51+
return ConnectionUpdates(stream: stream)
4352
}
4453

4554
public func sendMessage(token: UInt32, data: Data) async throws {

Tests/OpenGraphCxxTests/DebugServer/DebugServerTests.swift

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,37 @@ struct DebugServerTests {
2424

2525
@Test
2626
func commandTest() async throws {
27-
let debugServer = OG.DebugServer([.valid])
27+
var debugServer = OG.DebugServer([.valid])
2828
let cfURL = debugServer.copy_url()
2929
let url = try #require(cfURL) as URL
3030
let components = try #require(URLComponents(url: url, resolvingAgainstBaseURL: false))
3131
let token = try #require(components.queryItems?.first { $0.name == "token" }?.value.flatMap { UInt32($0) })
3232
debugServer.run(1)
3333
let client = DebugClient()
34-
try await client.connect(to: url)
35-
36-
for command in Command.allCases {
37-
if command == .graphDescription {
38-
continue
34+
let updates = client.connect(to: url)
35+
try await confirmation { confirm in
36+
for try await update in updates {
37+
switch update {
38+
case .ready:
39+
confirm()
40+
for command in Command.allCases {
41+
if command == .graphDescription {
42+
continue
43+
}
44+
try await client.sendMessage(
45+
token: token,
46+
data: data(for: command)
47+
)
48+
let (_, responseData) = try await client.receiveMessage()
49+
let response = try #require(String(data: responseData, encoding: .utf8))
50+
#expect(response == command.rawValue)
51+
}
52+
debugServer.shutdown()
53+
// TODO: The shutdown should close the connection, but it does not for OGDebugServer currently.
54+
default:
55+
break
56+
}
3957
}
40-
try await client.sendMessage(
41-
token: token,
42-
data: data(for: command)
43-
)
44-
let (_, responseData) = try await client.receiveMessage()
45-
let response = try #require(String(data: responseData, encoding: .utf8))
46-
#expect(response == command.rawValue)
4758
}
4859
}
4960
}

0 commit comments

Comments
 (0)