diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fb4f44f1e..de6e1ccdb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 0.48.2 — Unreleased ### Fixed +- Codex: SQLite cost saves no longer rescan every stored row and snapshot per file — baseline counts and file lookups are precomputed once, cutting a large-corpus (1,700+ sessions) save pass from minutes of CPU to seconds (refs #2760). - Codex: restore JSON-cache retention semantics lost in the SQLite cutover — discovery pruning now reaches the scanner's round-tripped payload so deleted files stop resurfacing, the row budget never sacrifices in-window or recently active sessions, and fork-parent protection again drops stale lineage-only parents (refs #2760). - Codex: the SQLite cost store no longer deletes the whole database on transient failures — lock contention from a concurrent CLI/app writer, disk-full, or a constraint violation now preserve history and only genuine corruption or schema drift triggers a rebuild, which is now logged (refs #2760). - Menu: let long metric reset and pace details wrap to two lines instead of truncating, without clipping cached card heights (#2742). Thanks @Yuxin-Qiao! diff --git a/Sources/CodexBarCore/Vendored/CostUsage/CostUsageStore+CodexCache.swift b/Sources/CodexBarCore/Vendored/CostUsage/CostUsageStore+CodexCache.swift index c4d83f4e2c..c1b2d2a8d1 100644 --- a/Sources/CodexBarCore/Vendored/CostUsage/CostUsageStore+CodexCache.swift +++ b/Sources/CodexBarCore/Vendored/CostUsage/CostUsageStore+CodexCache.swift @@ -25,17 +25,18 @@ extension CostUsageStore { let previous = self.readSnapshot() let canReuseStoredRows = previous.metadata.timeZoneIdentifier == calendar.timeZone.identifier self.deleteRemovedFiles(previous: previous, cache: cache) + let previousFilesByPath = Dictionary(uniqueKeysWithValues: previous.files.map { ($0.path, $0) }) + let snapshotCountsByPath = previous.tokenSnapshots + .reduce(into: [String: Int]()) { $0[$1.path, default: 0] += 1 } + let rowCountsByPath = previous.usageRows.reduce(into: [String: Int]()) { $0[$1.path, default: 0] += 1 } for (path, usage) in cache.files.sorted(by: { $0.key < $1.key }) { - let oldFile = previous.files.first { $0.path == path } - let oldSnapshotCount = previous.tokenSnapshots.count(where: { $0.path == path }) - let oldRowCount = previous.usageRows.count(where: { $0.path == path }) self.persistFile( path: path, usage: usage, baseline: PersistedFileBaseline( - file: oldFile, - snapshotCount: oldSnapshotCount, - rowCount: oldRowCount, + file: previousFilesByPath[path], + snapshotCount: snapshotCountsByPath[path] ?? 0, + rowCount: rowCountsByPath[path] ?? 0, canReuseRows: canReuseStoredRows), calendar: calendar) }