refactor(apple): share AsyncTimeout helper
This commit is contained in:
@@ -161,18 +161,10 @@ actor BridgeClient {
|
|||||||
purpose: String,
|
purpose: String,
|
||||||
_ op: @escaping @Sendable () async throws -> T) async throws -> T
|
_ op: @escaping @Sendable () async throws -> T) async throws -> T
|
||||||
{
|
{
|
||||||
try await withThrowingTaskGroup(of: T.self) { group in
|
try await AsyncTimeout.withTimeout(
|
||||||
group.addTask {
|
seconds: Double(seconds),
|
||||||
try await op()
|
onTimeout: { TimeoutError(purpose: purpose, seconds: seconds) },
|
||||||
}
|
operation: op)
|
||||||
group.addTask {
|
|
||||||
try await Task.sleep(nanoseconds: UInt64(seconds) * 1_000_000_000)
|
|
||||||
throw TimeoutError(purpose: purpose, seconds: seconds)
|
|
||||||
}
|
|
||||||
let result = try await group.next()!
|
|
||||||
group.cancelAll()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func startAndWaitForReady(_ connection: NWConnection, queue: DispatchQueue) async throws {
|
private func startAndWaitForReady(_ connection: NWConnection, queue: DispatchQueue) async throws {
|
||||||
|
|||||||
@@ -321,20 +321,10 @@ actor BridgeSession {
|
|||||||
seconds: Double,
|
seconds: Double,
|
||||||
operation: @escaping @Sendable () async throws -> T) async throws -> T
|
operation: @escaping @Sendable () async throws -> T) async throws -> T
|
||||||
{
|
{
|
||||||
try await withThrowingTaskGroup(of: T.self) { group in
|
try await AsyncTimeout.withTimeout(
|
||||||
group.addTask { try await operation() }
|
seconds: seconds,
|
||||||
group.addTask {
|
onTimeout: { TimeoutError(message: "UNAVAILABLE: connection timeout") },
|
||||||
try await Task.sleep(nanoseconds: UInt64(seconds * 1_000_000_000))
|
operation: operation)
|
||||||
throw TimeoutError(message: "UNAVAILABLE: connection timeout")
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let first = try await group.next() else {
|
|
||||||
throw TimeoutError(message: "UNAVAILABLE: connection timeout")
|
|
||||||
}
|
|
||||||
|
|
||||||
group.cancelAll()
|
|
||||||
return first
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func makeStateStream(for connection: NWConnection) -> AsyncStream<NWConnection.State> {
|
private static func makeStateStream(for connection: NWConnection) -> AsyncStream<NWConnection.State> {
|
||||||
|
|||||||
@@ -90,20 +90,7 @@ final class LocationService: NSObject, CLLocationManagerDelegate {
|
|||||||
timeoutMs: Int,
|
timeoutMs: Int,
|
||||||
operation: @escaping @Sendable () async throws -> T) async throws -> T
|
operation: @escaping @Sendable () async throws -> T) async throws -> T
|
||||||
{
|
{
|
||||||
if timeoutMs == 0 {
|
try await AsyncTimeout.withTimeoutMs(timeoutMs: timeoutMs, onTimeout: { Error.timeout }, operation: operation)
|
||||||
return try await operation()
|
|
||||||
}
|
|
||||||
|
|
||||||
return try await withThrowingTaskGroup(of: T.self) { group in
|
|
||||||
group.addTask { try await operation() }
|
|
||||||
group.addTask {
|
|
||||||
try await Task.sleep(nanoseconds: UInt64(timeoutMs) * 1_000_000)
|
|
||||||
throw Error.timeout
|
|
||||||
}
|
|
||||||
let result = try await group.next()!
|
|
||||||
group.cancelAll()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func accuracyValue(_ accuracy: ClawdbotLocationAccuracy) -> CLLocationAccuracy {
|
private static func accuracyValue(_ accuracy: ClawdbotLocationAccuracy) -> CLLocationAccuracy {
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum AsyncTimeout {
|
public enum AsyncTimeout {
|
||||||
static func withTimeout<T: Sendable>(
|
public static func withTimeout<T: Sendable>(
|
||||||
seconds: Double,
|
seconds: Double,
|
||||||
onTimeout: @escaping @Sendable () -> Error,
|
onTimeout: @escaping @Sendable () -> Error,
|
||||||
operation: @escaping @Sendable () async throws -> T) async throws -> T
|
operation: @escaping @Sendable () async throws -> T) async throws -> T
|
||||||
{
|
{
|
||||||
let clamped = max(0, seconds)
|
let clamped = max(0, seconds)
|
||||||
|
if clamped == 0 {
|
||||||
|
return try await operation()
|
||||||
|
}
|
||||||
|
|
||||||
return try await withThrowingTaskGroup(of: T.self) { group in
|
return try await withThrowingTaskGroup(of: T.self) { group in
|
||||||
group.addTask { try await operation() }
|
group.addTask { try await operation() }
|
||||||
group.addTask {
|
group.addTask {
|
||||||
@@ -19,4 +23,14 @@ enum AsyncTimeout {
|
|||||||
throw onTimeout()
|
throw onTimeout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func withTimeoutMs<T: Sendable>(
|
||||||
|
timeoutMs: Int,
|
||||||
|
onTimeout: @escaping @Sendable () -> Error,
|
||||||
|
operation: @escaping @Sendable () async throws -> T) async throws -> T
|
||||||
|
{
|
||||||
|
let clamped = max(0, timeoutMs)
|
||||||
|
let seconds = Double(clamped) / 1000.0
|
||||||
|
return try await self.withTimeout(seconds: seconds, onTimeout: onTimeout, operation: operation)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user