fix superClient

This commit is contained in:
anlicheng 2026-05-27 17:46:30 +08:00
parent 4b005cb75d
commit 3cdf1953bf

View File

@ -22,9 +22,7 @@ actor SDLSuperClient {
// //
public let messageStream: AsyncThrowingStream<SDLQUICInboundMessage, Error> public let messageStream: AsyncThrowingStream<SDLQUICInboundMessage, Error>
private let messageCont: AsyncThrowingStream<SDLQUICInboundMessage, Error>.Continuation private let messageCont: AsyncThrowingStream<SDLQUICInboundMessage, Error>.Continuation
private var pendingConnectionError: Error?
private let connection: NWConnection private let connection: NWConnection
private let maxBufferSize: Int private let maxBufferSize: Int
@ -68,21 +66,14 @@ actor SDLSuperClient {
return return
} }
self.connection.stateUpdateHandler = { [weak self] state in let stateStream = Self.makeStateStream(for: self.connection)
SDLLogger.log("[SDLSuperClient] new state: \(state)", for: .debug)
Task {
await self?.handleConnectionState(state: state)
}
}
self.connection.start(queue: queue)
defer { defer {
self.stop() self.stop()
} }
try await withTaskCancellationHandler { try await withTaskCancellationHandler {
try await self.waitUntilReady() self.connection.start(queue: self.queue)
try await self.readLoop() try await self.runStateLoop(stateStream)
} onCancel: { } onCancel: {
self.connection.cancel() self.connection.cancel()
} }
@ -99,35 +90,48 @@ actor SDLSuperClient {
preconditionFailure("invalid super server IP: \(ip)") preconditionFailure("invalid super server IP: \(ip)")
} }
private func handleConnectionState(state: NWConnection.State) { private static func makeStateStream(for connection: NWConnection) -> AsyncThrowingStream<NWConnection.State, Error> {
switch state { return AsyncThrowingStream(bufferingPolicy: .bufferingNewest(16)) { continuation in
case .ready: connection.stateUpdateHandler = { state in
self.state = .running SDLLogger.log("[SDLSuperClient] new state: \(state)", for: .debug)
case .failed(let error): continuation.yield(state)
self.pendingConnectionError = SDLSuperError.connectionFailed(error)
self.messageCont.finish(throwing: SDLSuperError.connectionFailed(error)) switch state {
case .cancelled: case .failed(let error):
self.pendingConnectionError = SDLSuperError.connectionCancelled continuation.finish(throwing: SDLSuperError.connectionFailed(error))
self.messageCont.finish(throwing: SDLSuperError.connectionCancelled) case .cancelled:
default: continuation.finish(throwing: SDLSuperError.connectionCancelled)
() default:
break
}
}
continuation.onTermination = { _ in
connection.stateUpdateHandler = nil
}
} }
} }
private func waitUntilReady() async throws { private func runStateLoop(_ stateStream: AsyncThrowingStream<NWConnection.State, Error>) async throws {
while true { for try await state in stateStream {
try Task.checkCancellation() try Task.checkCancellation()
if case .running = self.state { switch state {
case .ready:
self.state = .running
try await self.readLoop()
return return
case .failed(let error):
let wrappedError = SDLSuperError.connectionFailed(error)
self.messageCont.finish(throwing: wrappedError)
throw wrappedError
case .cancelled:
self.messageCont.finish(throwing: SDLSuperError.connectionCancelled)
throw SDLSuperError.connectionCancelled
default:
break
} }
if let pendingConnectionError {
throw pendingConnectionError
}
try await Task.sleep(for: .milliseconds(100))
} }
} }