refactor(macos): replace gateway NotificationCenter with event bus

This commit is contained in:
Peter Steinberger
2025-12-12 22:06:40 +00:00
parent 9cf457be0a
commit 6a7f955818
10 changed files with 378 additions and 127 deletions

View File

@@ -70,6 +70,11 @@ import Testing
self.pendingReceiveHandler.withLock { $0 = completionHandler }
}
func emitIncoming(_ data: Data) {
let handler = self.pendingReceiveHandler.withLock { $0 }
handler?(Result<URLSessionWebSocketTask.Message, Error>.success(.data(data)))
}
private static func helloOkData() -> Data {
let json = """
{
@@ -118,6 +123,10 @@ import Testing
}
}
func latestTask() -> FakeWebSocketTask? {
self.tasks.withLock { $0.last }
}
func makeWebSocketTask(url: URL) -> WebSocketTaskBox {
_ = url
self.makeCount.withLock { $0 += 1 }
@@ -185,4 +194,74 @@ import Testing
#expect(session.snapshotMakeCount() == 1)
}
@Test func subscribeReplaysLatestSnapshot() async throws {
let session = FakeWebSocketSession()
let url = URL(string: "ws://example.invalid")!
let cfg = ConfigSource(token: nil)
let conn = GatewayConnection(
configProvider: { (url, cfg.snapshotToken()) },
sessionBox: WebSocketSessionBox(session: session))
_ = try await conn.request(method: "status", params: nil)
let stream = await conn.subscribe(bufferingNewest: 10)
var iterator = stream.makeAsyncIterator()
let first = await iterator.next()
guard case let .snapshot(snap) = first else {
Issue.record("expected snapshot, got \(String(describing: first))")
return
}
#expect(snap.type == "hello-ok")
}
@Test func subscribeEmitsSeqGapBeforeEvent() async throws {
let session = FakeWebSocketSession()
let url = URL(string: "ws://example.invalid")!
let cfg = ConfigSource(token: nil)
let conn = GatewayConnection(
configProvider: { (url, cfg.snapshotToken()) },
sessionBox: WebSocketSessionBox(session: session))
let stream = await conn.subscribe(bufferingNewest: 10)
var iterator = stream.makeAsyncIterator()
_ = try await conn.request(method: "status", params: nil)
_ = await iterator.next() // snapshot
let evt1 = Data(
"""
{"type":"event","event":"presence","payload":{"presence":[]},"seq":1}
""".utf8)
session.latestTask()?.emitIncoming(evt1)
let firstEvent = await iterator.next()
guard case let .event(firstFrame) = firstEvent else {
Issue.record("expected event, got \(String(describing: firstEvent))")
return
}
#expect(firstFrame.seq == 1)
let evt3 = Data(
"""
{"type":"event","event":"presence","payload":{"presence":[]},"seq":3}
""".utf8)
session.latestTask()?.emitIncoming(evt3)
let gap = await iterator.next()
guard case let .seqGap(expected, received) = gap else {
Issue.record("expected seqGap, got \(String(describing: gap))")
return
}
#expect(expected == 2)
#expect(received == 3)
let secondEvent = await iterator.next()
guard case let .event(secondFrame) = secondEvent else {
Issue.record("expected event, got \(String(describing: secondEvent))")
return
}
#expect(secondFrame.seq == 3)
}
}