fix: expose RPC watch debounce

This commit is contained in:
Peter Steinberger 2026-05-04 07:00:45 +01:00
parent f0cd725c70
commit 60ed8a9f02
No known key found for this signature in database
5 changed files with 46 additions and 1 deletions

View File

@ -2,6 +2,7 @@
## Unreleased
- feat: add `imsg group` chat metadata lookup and group fields to `chats --json` (#88, thanks @mryanb)
- fix: expose RPC watch debounce and default it to 500ms to reduce outbound echo races (#72, #80)
- fix: speed up chat listing by using `chat_message_join.message_date` when available (#76, thanks @tmad4000)
- fix: speed up JSON history metadata lookups by batching attachments and reactions (#81, thanks @kacy)
- docs: clarify stale Full Disk Access and Terminal.app troubleshooting (#28, #32, #33, #83)

View File

@ -115,3 +115,14 @@ func stringArrayParam(_ value: Any?) -> [String] {
}
return []
}
let defaultRPCWatchDebounceInterval: TimeInterval = 0.5
func watchDebounceIntervalParam(_ params: [String: Any]) throws -> TimeInterval {
let raw = params["debounce_ms"] ?? params["debounceMs"]
guard let raw else { return defaultRPCWatchDebounceInterval }
guard let milliseconds = intParam(raw), milliseconds >= 0 else {
throw RPCError.invalidParams("debounce_ms must be a non-negative integer")
}
return Double(milliseconds) / 1000
}

View File

@ -70,12 +70,16 @@ extension RPCServer {
let endISO = stringParam(params["end"])
let includeAttachments = boolParam(params["attachments"]) ?? false
let includeReactions = boolParam(params["include_reactions"]) ?? false
let debounceInterval = try watchDebounceIntervalParam(params)
let filter = try MessageFilter.fromISO(
participants: participants,
startISO: startISO,
endISO: endISO
)
let config = MessageWatcherConfiguration(includeReactions: includeReactions)
let config = MessageWatcherConfiguration(
debounceInterval: debounceInterval,
includeReactions: includeReactions
)
let subID = await subscriptions.allocateID()
let localStore = store
let localWatcher = watcher

View File

@ -120,6 +120,30 @@ func messagePayloadOmitsEmptyReplyToGuid() throws {
#expect(payload["guid"] as? String == "msg-guid-6")
}
@Test
func watchDebounceIntervalDefaultsToHalfSecond() throws {
#expect(try watchDebounceIntervalParam([:]) == 0.5)
}
@Test
func watchDebounceIntervalAcceptsSnakeAndCamelCaseMilliseconds() throws {
#expect(try watchDebounceIntervalParam(["debounce_ms": 750]) == 0.75)
#expect(try watchDebounceIntervalParam(["debounceMs": "125"]) == 0.125)
}
@Test
func watchDebounceIntervalRejectsInvalidValues() {
do {
_ = try watchDebounceIntervalParam(["debounce_ms": -1])
#expect(Bool(false))
} catch let error as RPCError {
#expect(error.code == -32602)
#expect(error.data?.contains("debounce_ms") == true)
} catch {
#expect(Bool(false))
}
}
@Test
func paramParsingHelpers() {
#expect(stringParam(123 as NSNumber) == "123")

View File

@ -38,11 +38,16 @@ Params:
- `start` / `end` (ISO8601, optional)
- `attachments` (bool, default false)
- `include_reactions` (bool, default false)
- `debounce_ms` / `debounceMs` (int milliseconds, default 500)
Result:
- `{ "subscription": 1 }`
Notifications:
- `{"jsonrpc":"2.0","method":"message","params":{"subscription":1,"message":<Message>}}`
The RPC default debounce is intentionally higher than the CLI default so macOS
has time to settle follow-up writes such as `is_from_me` updates on outbound
messages. Clients that need lower latency can pass `debounce_ms`.
### `watch.unsubscribe`
Params:
- `subscription` (int, required)