Session Cache Implementation
Nucleic-Session: B2346642-3353-4BD5-9DE2-A8B77BD66C98 Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
@@ -647,6 +647,48 @@ final class RemoteStore: ObservableObject {
|
|||||||
return bySeq.values.sorted { $0.seq < $1.seq }
|
return bySeq.values.sorted { $0.seq < $1.seq }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Offline cache (SessionCache)
|
||||||
|
|
||||||
|
/// Debounced write of the live session list to disk, so a read-only history survives a
|
||||||
|
/// disconnect / relaunch.
|
||||||
|
private func persistSummaries(_ list: [WireSessionSummary]) {
|
||||||
|
summaryPersistTask?.cancel()
|
||||||
|
summaryPersistTask = Task { [list] in
|
||||||
|
try? await Task.sleep(nanoseconds: 2_000_000_000)
|
||||||
|
guard !Task.isCancelled else { return }
|
||||||
|
await SessionCache.saveSummaries(list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Seed the open transcript from disk so a cached session's history shows instantly — even fully
|
||||||
|
/// offline. A live snapshot/backfill merges on top by seq (dedup), so this never double-counts.
|
||||||
|
private func loadCachedTranscript(_ sessionID: SessionID) {
|
||||||
|
Task { [weak self] in
|
||||||
|
let cached = await SessionCache.loadEvents(sessionID)
|
||||||
|
guard let self, self.openSessionID == sessionID, !cached.isEmpty else { return }
|
||||||
|
self.openEvents = Self.mergedEvents(cached, self.openEvents)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Debounced write of the open transcript, called after each batch of events lands.
|
||||||
|
private func persistOpenTranscript() {
|
||||||
|
guard !demoMode, let id = openSessionID, !openEvents.isEmpty else { return }
|
||||||
|
let events = openEvents
|
||||||
|
transcriptPersistTask?.cancel()
|
||||||
|
transcriptPersistTask = Task { [events, id] in
|
||||||
|
try? await Task.sleep(nanoseconds: 1_500_000_000)
|
||||||
|
guard !Task.isCancelled else { return }
|
||||||
|
await SessionCache.saveEvents(events, for: id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Flush the open transcript to disk immediately (on close), cancelling any pending debounce.
|
||||||
|
private func flushOpenTranscript(_ id: SessionID, _ events: [AgentEvent]) {
|
||||||
|
transcriptPersistTask?.cancel()
|
||||||
|
guard !demoMode, !events.isEmpty else { return }
|
||||||
|
Task { await SessionCache.saveEvents(events, for: id) }
|
||||||
|
}
|
||||||
|
|
||||||
/// The flat sessions list: every connected Mac's sessions, deduped by id (ids are globally
|
/// The flat sessions list: every connected Mac's sessions, deduped by id (ids are globally
|
||||||
/// unique). Views handle sorting/grouping.
|
/// unique). Views handle sorting/grouping.
|
||||||
private func aggregatedSessions() -> [WireSessionSummary] {
|
private func aggregatedSessions() -> [WireSessionSummary] {
|
||||||
|
|||||||
Reference in New Issue
Block a user