Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 48 additions & 34 deletions MeoAsstMac/Core/MaaToolClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation
import Network

actor MaaToolClient {
private let connection: NWConnection
private var connection: NWConnection

init?(address: String) async {
let parts = address.split(separator: ":")
Expand All @@ -21,51 +21,65 @@ actor MaaToolClient {
}
let host = NWEndpoint.Host(String(parts[0]))

connection = NWConnection(host: host, port: port, using: .tcp)
var retryCount = 0
let maxRetries = 20

let states = AsyncStream<NWConnection.State> { continuation in
connection.stateUpdateHandler = { state in
if state == .ready {
continuation.finish()
} else {
continuation.yield(state)
while retryCount < maxRetries {
connection = NWConnection(host: host, port: port, using: .tcp)

let states = AsyncStream<NWConnection.State> { continuation in
connection.stateUpdateHandler = { state in
continuation.yield(state)
}
}

continuation.onTermination = { [weak self] reason in
guard reason == .cancelled else { return }
self?.connection.cancel()
continuation.onTermination = { [weak self] reason in
guard reason == .cancelled else { return }
Task {
await self?.cancelActorConnection()
}
}
}
}

connection.start(queue: .global())
connection.start(queue: .global())

var retryCount = 0
let maxRetries = 20
state_enum: for await state in states {
switch state {
case .setup, .preparing, .cancelled:
break
case .waiting, .failed:
retryCount += 1
if retryCount >= maxRetries {
connection.cancel()
break state_enum
}

for await state in states {
switch state {
case .setup, .preparing, .cancelled:
break
case .waiting:
try? await Task.sleep(for: .seconds(0.5))
connection.restart()
case .failed:
retryCount += 1
if retryCount > maxRetries {
connection.cancel() // 取消连接
return nil // 达到最大重试次数,初始化失败
try? await Task.sleep(for: .seconds(0.5))

if case .failed = state {
// 明确失败,清理旧连接,让外部循环创建新连接
connection.cancel()
break state_enum
} else {
// .waiting 状态下,使用 restart()
connection.restart()
}
case .ready:
return
@unknown default:
fatalError()
}
try? await Task.sleep(nanoseconds: 500_000_000)
connection.restart()
case .ready:
return
@unknown default:
fatalError()
}
}
return nil
}

// MARK: - Private Methods
private func cancelActorConnection() {
connection.cancel()
}

// MARK: - Public Methods

func terminate() async throws {
guard connection.state == .ready else { return }

Expand Down