Skip to content

Commit 4c85d16

Browse files
committed
fix: extend bridge send timeout
1 parent 041b406 commit 4c85d16

3 files changed

Lines changed: 54 additions & 3 deletions

File tree

Sources/IMsgCore/IMsgBridgeClient.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,16 @@ public final class IMsgBridgeClient: @unchecked Sendable {
4141
public func invoke(
4242
action: BridgeAction,
4343
params: [String: Any] = [:],
44-
timeout: TimeInterval = IMsgBridgeProtocol.defaultResponseTimeout
44+
timeout: TimeInterval? = nil
4545
) async throws -> [String: Any] {
46+
let effectiveTimeout = timeout ?? IMsgBridgeProtocol.defaultResponseTimeout(for: action)
4647
if useLegacyIPC {
4748
try launcher.ensureRunning()
4849
return try await invokeLegacy(action: action, params: params)
4950
}
5051

5152
try launcher.ensureLaunched()
52-
return try await invokeV2(action: action, params: params, timeout: timeout)
53+
return try await invokeV2(action: action, params: params, timeout: effectiveTimeout)
5354
}
5455

5556
// MARK: - v2 path

Sources/IMsgCore/IMsgBridgeProtocol.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,21 @@ public enum IMsgBridgeProtocol {
2222
public static let rotatedEventsFileName: String = ".imsg-events.jsonl.1"
2323
public static let eventsRotationBytes: Int = 1 * 1024 * 1024
2424

25-
/// Default per-request timeout for synchronous RPC waits.
25+
/// Default per-request timeout for synchronous non-send RPC waits.
2626
public static let defaultResponseTimeout: TimeInterval = 10.0
27+
28+
/// Default timeout for send-style bridge waits. macOS 26 private sends can
29+
/// stall for well over the probe window before Messages.app returns.
30+
public static let defaultSendResponseTimeout: TimeInterval = 150.0
31+
32+
public static func defaultResponseTimeout(for action: BridgeAction) -> TimeInterval {
33+
switch action {
34+
case .sendMessage, .sendMultipart, .sendAttachment, .sendPoll, .sendReaction:
35+
return defaultSendResponseTimeout
36+
default:
37+
return defaultResponseTimeout
38+
}
39+
}
2740
}
2841

2942
/// All action verbs exposed by the v2 bridge. Names match the BlueBubbles

Tests/IMsgCoreTests/IMsgBridgeProtocolTests.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,41 @@ struct IMsgBridgeProtocolTests {
8282
#expect(response.success == false)
8383
#expect(response.error == "Chat not found")
8484
}
85+
86+
@Test
87+
func bridgeProtocolUsesLongerDefaultForSendActions() {
88+
#expect(IMsgBridgeProtocol.defaultResponseTimeout == 10.0)
89+
#expect(IMsgBridgeProtocol.defaultSendResponseTimeout == 150.0)
90+
91+
for action in [
92+
BridgeAction.sendMessage,
93+
.sendMultipart,
94+
.sendAttachment,
95+
.sendPoll,
96+
.sendReaction,
97+
] {
98+
#expect(
99+
IMsgBridgeProtocol.defaultResponseTimeout(for: action)
100+
== IMsgBridgeProtocol.defaultSendResponseTimeout
101+
)
102+
}
103+
}
104+
105+
@Test
106+
func bridgeProtocolKeepsShortDefaultForNonSendActions() {
107+
for action in [
108+
BridgeAction.status,
109+
.typing,
110+
.read,
111+
.editMessage,
112+
.unsendMessage,
113+
.deleteMessage,
114+
.notifyAnyways,
115+
] {
116+
#expect(
117+
IMsgBridgeProtocol.defaultResponseTimeout(for: action)
118+
== IMsgBridgeProtocol.defaultResponseTimeout
119+
)
120+
}
121+
}
85122
}

0 commit comments

Comments
 (0)