fix(node): avoid invoke result deadlock
This commit is contained in:
committed by
Peter Steinberger
parent
7e9aa3c275
commit
81e915110e
@@ -643,6 +643,52 @@ public actor GatewayChannelActor {
|
|||||||
return Data() // Should not happen, but tolerate empty payloads.
|
return Data() // Should not happen, but tolerate empty payloads.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func send(method: String, params: [String: AnyCodable]?) async throws {
|
||||||
|
do {
|
||||||
|
try await self.connect()
|
||||||
|
} catch {
|
||||||
|
throw self.wrap(error, context: "gateway connect")
|
||||||
|
}
|
||||||
|
let id = UUID().uuidString
|
||||||
|
let paramsObject: ProtoAnyCodable? = params.map { entries in
|
||||||
|
let dict = entries.reduce(into: [String: ProtoAnyCodable]()) { dict, entry in
|
||||||
|
dict[entry.key] = ProtoAnyCodable(entry.value.value)
|
||||||
|
}
|
||||||
|
return ProtoAnyCodable(dict)
|
||||||
|
}
|
||||||
|
let frame = RequestFrame(
|
||||||
|
type: "req",
|
||||||
|
id: id,
|
||||||
|
method: method,
|
||||||
|
params: paramsObject)
|
||||||
|
let data: Data
|
||||||
|
do {
|
||||||
|
data = try self.encoder.encode(frame)
|
||||||
|
} catch {
|
||||||
|
self.logger.error(
|
||||||
|
"gateway send encode failed \(method, privacy: .public) error=\(error.localizedDescription, privacy: .public)")
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
guard let task = self.task else {
|
||||||
|
throw NSError(
|
||||||
|
domain: "Gateway",
|
||||||
|
code: 5,
|
||||||
|
userInfo: [NSLocalizedDescriptionKey: "gateway socket unavailable"])
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
try await task.send(.data(data))
|
||||||
|
} catch {
|
||||||
|
let wrapped = self.wrap(error, context: "gateway send \(method)")
|
||||||
|
self.connected = false
|
||||||
|
self.task?.cancel(with: .goingAway, reason: nil)
|
||||||
|
Task { [weak self] in
|
||||||
|
guard let self else { return }
|
||||||
|
await self.scheduleReconnect()
|
||||||
|
}
|
||||||
|
throw wrapped
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Wrap low-level URLSession/WebSocket errors with context so UI can surface them.
|
// Wrap low-level URLSession/WebSocket errors with context so UI can surface them.
|
||||||
private func wrap(_ error: Error, context: String) -> Error {
|
private func wrap(_ error: Error, context: String) -> Error {
|
||||||
if let urlError = error as? URLError {
|
if let urlError = error as? URLError {
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ public actor GatewayNodeSession {
|
|||||||
"payloadJSON": AnyCodable(payloadJSON ?? NSNull()),
|
"payloadJSON": AnyCodable(payloadJSON ?? NSNull()),
|
||||||
]
|
]
|
||||||
do {
|
do {
|
||||||
_ = try await channel.request(method: "node.event", params: params, timeoutMs: 8000)
|
try await channel.send(method: "node.event", params: params)
|
||||||
} catch {
|
} catch {
|
||||||
self.logger.error("node event failed: \(error.localizedDescription, privacy: .public)")
|
self.logger.error("node event failed: \(error.localizedDescription, privacy: .public)")
|
||||||
}
|
}
|
||||||
@@ -224,7 +224,7 @@ public actor GatewayNodeSession {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
_ = try await channel.request(method: "node.invoke.result", params: params, timeoutMs: 15000)
|
try await channel.send(method: "node.invoke.result", params: params)
|
||||||
} catch {
|
} catch {
|
||||||
self.logger.error("node invoke result failed: \(error.localizedDescription, privacy: .public)")
|
self.logger.error("node invoke result failed: \(error.localizedDescription, privacy: .public)")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user