mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-08 02:14:37 +00:00
feat(scarfmon): A1 — instrument iOS file-watcher polling cadence
Adds three measure points to CitadelServerTransport.watchPaths: - ios.fileWatcher.tick (interval) — full poll cycle latency including the SSH stat round-trips. > 1500ms here is what 'out of sync' feels like — the channel is congested or the host is slow. - ios.fileWatcher.delta (event) — fires only when the signature actually changed. Low delta/tick ratio means we can safely drop the 3-second cadence; high ratio means we'd just burn bandwidth. - ios.fileWatcher.paths (event, bytes=count) — number of paths watched per cycle. Explains slow ticks as the project list grows. Surgical addition; existing 3-second cadence + signature-diff logic unchanged. With Full mode on, a few minutes of usage on LAN will tell us empirically whether the cadence can drop to 1s — the original v2.6.0 user feedback complained 'chat is out of sync' between iOS and Mac on a fast LAN. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -272,14 +272,32 @@ public final class CitadelServerTransport: ServerTransport, @unchecked Sendable
|
||||
// Polling-based, identical in shape to `SSHTransport`'s remote-
|
||||
// watch fallback: stat each path, yield `.anyChanged` when any
|
||||
// mtime shifts. 3s tick keeps bandwidth low.
|
||||
//
|
||||
// ScarfMon — A1 instrumentation:
|
||||
// - `ios.fileWatcher.tick` (interval) — full poll cycle latency,
|
||||
// includes the SSH stat round-trips. Pre-fix this is what an
|
||||
// "out of sync" user is feeling: anything > 1500 ms means
|
||||
// the channel is congested or the host is slow.
|
||||
// - `ios.fileWatcher.delta` (event) — fires only when the
|
||||
// signature actually changed. Low ratio (delta count / tick
|
||||
// count) means we're polling more aggressively than the
|
||||
// change rate warrants — opens the door to dropping the 3s
|
||||
// cadence on LAN.
|
||||
// - `ios.fileWatcher.paths` (event with bytes=count) — number
|
||||
// of paths watched per cycle, helps explain a slow tick when
|
||||
// the project list grows.
|
||||
AsyncStream { continuation in
|
||||
let task = Task.detached { [weak self] in
|
||||
var lastSignature = ""
|
||||
while !Task.isCancelled {
|
||||
guard let self else { break }
|
||||
let current = await self.buildWatchSignature(for: paths)
|
||||
ScarfMon.event(.transport, "ios.fileWatcher.paths", count: 1, bytes: paths.count)
|
||||
let current = await ScarfMon.measureAsync(.transport, "ios.fileWatcher.tick") {
|
||||
await self.buildWatchSignature(for: paths)
|
||||
}
|
||||
if !current.isEmpty, current != lastSignature {
|
||||
if !lastSignature.isEmpty {
|
||||
ScarfMon.event(.transport, "ios.fileWatcher.delta", count: 1)
|
||||
continuation.yield(.anyChanged)
|
||||
}
|
||||
lastSignature = current
|
||||
|
||||
Reference in New Issue
Block a user