perf: move SwiftData cache and JSON encode off main thread during sync
- cacheStories() runs in Task.detached with a background ModelContext - persistQuickCache() encodes 100 stories off-thread via Task.detached - loadSectionSupplements() batches 5 parallel fetches into one sectionSupplement write Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ struct SignalFeedView: View {
|
||||
@EnvironmentObject var ws: WebSocketManager
|
||||
@EnvironmentObject var settings: ServerSettings
|
||||
@Environment(\.modelContext) private var modelContext
|
||||
@Environment(\.modelContainer) private var modelContainer
|
||||
|
||||
@Query private var cachedStories: [CachedStory]
|
||||
@Query private var cachedArticles: [CachedArticle]
|
||||
@@ -723,22 +724,25 @@ struct SignalFeedView: View {
|
||||
|
||||
private func cacheStories(_ stories: [StorySummary]) {
|
||||
guard !stories.isEmpty else { return }
|
||||
// One fetch + an in-memory index, instead of a query per story.
|
||||
let existing = (try? modelContext.fetch(FetchDescriptor<CachedStory>())) ?? []
|
||||
var byId = Dictionary(existing.map { ($0.id, $0) }, uniquingKeysWith: { a, _ in a })
|
||||
for summary in stories {
|
||||
if let found = byId[summary.id] {
|
||||
found.signalScore = summary.signalScore
|
||||
found.sourceCount = summary.sourceCount
|
||||
found.tags = summary.tags ?? []
|
||||
found.updatedAt = summary.updatedAt
|
||||
} else {
|
||||
let c = CachedStory(from: summary)
|
||||
modelContext.insert(c)
|
||||
byId[summary.id] = c
|
||||
let container = modelContainer
|
||||
Task.detached {
|
||||
let ctx = ModelContext(container)
|
||||
let existing = (try? ctx.fetch(FetchDescriptor<CachedStory>())) ?? []
|
||||
var byId = Dictionary(existing.map { ($0.id, $0) }, uniquingKeysWith: { a, _ in a })
|
||||
for summary in stories {
|
||||
if let found = byId[summary.id] {
|
||||
found.signalScore = summary.signalScore
|
||||
found.sourceCount = summary.sourceCount
|
||||
found.tags = summary.tags ?? []
|
||||
found.updatedAt = summary.updatedAt
|
||||
} else {
|
||||
let c = CachedStory(from: summary)
|
||||
ctx.insert(c)
|
||||
byId[summary.id] = c
|
||||
}
|
||||
}
|
||||
try? ctx.save()
|
||||
}
|
||||
try? modelContext.save()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user