feat: v2
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import Foundation
|
||||
import os
|
||||
|
||||
/// Последний удачный ответ API.
|
||||
struct MarketSnapshot: Codable, Sendable {
|
||||
let date: Date
|
||||
let thumbs: [SymbolThumb]
|
||||
let histories: [String: [Double]]
|
||||
}
|
||||
|
||||
/// Дисковый кэш снимка рынка в контейнере App Group.
|
||||
///
|
||||
/// Офлайн-фолбэк: без сети виджет показывает последние реальные котировки
|
||||
/// с честной меткой времени, а не фиктивные данные.
|
||||
struct MarketSnapshotCache: Sendable {
|
||||
private let fileURL: URL?
|
||||
|
||||
private static let logger = Logger(subsystem: AppGroup.id, category: "snapshot-cache")
|
||||
|
||||
init() {
|
||||
fileURL = AppGroup.cachesURL?.appendingPathComponent("market-snapshot.json")
|
||||
}
|
||||
|
||||
func load() -> MarketSnapshot? {
|
||||
guard let fileURL, let data = try? Data(contentsOf: fileURL) else { return nil }
|
||||
do {
|
||||
return try JSONDecoder().decode(MarketSnapshot.self, from: data)
|
||||
} catch {
|
||||
Self.logger.error("Кэш повреждён: \(String(describing: error), privacy: .public)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func save(_ snapshot: MarketSnapshot) {
|
||||
guard let fileURL else { return }
|
||||
do {
|
||||
try FileManager.default.createDirectory(
|
||||
at: fileURL.deletingLastPathComponent(),
|
||||
withIntermediateDirectories: true
|
||||
)
|
||||
try JSONEncoder().encode(snapshot).write(to: fileURL, options: .atomic)
|
||||
} catch {
|
||||
Self.logger.error("Кэш не сохранён: \(String(describing: error), privacy: .public)")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user