Cache fixes

This commit is contained in:
Arkadiusz Fal
2022-12-12 10:21:46 +01:00
parent 25da312966
commit a35d697ebe
10 changed files with 119 additions and 118 deletions

View File

@@ -0,0 +1,36 @@
import Cache
import Foundation
import Logging
import SwiftyJSON
struct BaseCacheModel {
static var shared = BaseCacheModel()
static let jsonToDataTransformer: (JSON) -> Data = { try! $0.rawData() }
static let jsonFromDataTransformer: (Data) -> JSON = { try! JSON(data: $0) }
static let jsonTransformer = Transformer(toData: jsonToDataTransformer, fromData: jsonFromDataTransformer)
var models: [CacheModel] {
[
FeedCacheModel.shared,
VideosCacheModel.shared,
PlaylistsCacheModel.shared,
ChannelPlaylistsCacheModel.shared,
SubscribedChannelsModel.shared
]
}
func clear() {
models.forEach { $0.clear() }
}
var totalSize: Int {
models.compactMap { $0.storage?.totalDiskStorageSize }.reduce(0, +)
}
var totalSizeFormatted: String {
byteCountFormatter.string(fromByteCount: Int64(totalSize))
}
private var byteCountFormatter: ByteCountFormatter { .init() }
}

View File

@@ -1,29 +1,24 @@
import Cache
import Foundation
import Logging
import SwiftyJSON
struct CacheModel {
static var shared = CacheModel()
protocol CacheModel {
var storage: Storage<String, JSON>? { get }
static let jsonToDataTransformer: (JSON) -> Data = { try! $0.rawData() }
static let jsonFromDataTransformer: (Data) -> JSON = { try! JSON(data: $0) }
static let jsonTransformer = Transformer(toData: jsonToDataTransformer, fromData: jsonFromDataTransformer)
func clear()
}
extension CacheModel {
func clear() {
FeedCacheModel.shared.clear()
VideosCacheModel.shared.clear()
PlaylistsCacheModel.shared.clear()
try? storage?.removeAll()
}
var totalSize: Int {
(FeedCacheModel.shared.storage.totalDiskStorageSize ?? 0) +
(VideosCacheModel.shared.storage.totalDiskStorageSize ?? 0) +
(PlaylistsCacheModel.shared.storage.totalDiskStorageSize ?? 0)
}
func getFormattedDate(_ date: Date?) -> String {
guard let date else { return "unknown" }
var totalSizeFormatted: String {
byteCountFormatter.string(fromByteCount: Int64(totalSize))
let isSameDay = Calendar(identifier: .iso8601).isDate(date, inSameDayAs: Date())
let formatter = isSameDay ? dateFormatterForTimeOnly : dateFormatter
return formatter.string(from: date)
}
var dateFormatter: DateFormatter {
@@ -43,6 +38,4 @@ struct CacheModel {
}
var iso8601DateFormatter: ISO8601DateFormatter { .init() }
private var byteCountFormatter: ByteCountFormatter { .init() }
}

View File

@@ -3,32 +3,32 @@ import Foundation
import Logging
import SwiftyJSON
struct ChannelPlaylistsCacheModel {
struct ChannelPlaylistsCacheModel: CacheModel {
static let shared = ChannelPlaylistsCacheModel()
let logger = Logger(label: "stream.yattee.cache.channel-playlists")
static let diskConfig = DiskConfig(name: "channel-playlists")
static let memoryConfig = MemoryConfig()
let storage = try! Storage<String, JSON>(
var storage = try? Storage<String, JSON>(
diskConfig: Self.diskConfig,
memoryConfig: Self.memoryConfig,
transformer: CacheModel.jsonTransformer
transformer: BaseCacheModel.jsonTransformer
)
func storePlaylist(playlist: ChannelPlaylist) {
let date = CacheModel.shared.iso8601DateFormatter.string(from: Date())
let date = iso8601DateFormatter.string(from: Date())
logger.info("STORE \(playlistCacheKey(playlist.id)) -- \(date)")
let feedTimeObject: JSON = ["date": date]
let playlistObject: JSON = ["playlist": playlist.json.object]
try? storage.setObject(feedTimeObject, forKey: playlistTimeCacheKey(playlist.id))
try? storage.setObject(playlistObject, forKey: playlistCacheKey(playlist.id))
try? storage?.setObject(feedTimeObject, forKey: playlistTimeCacheKey(playlist.id))
try? storage?.setObject(playlistObject, forKey: playlistCacheKey(playlist.id))
}
func retrievePlaylist(_ id: ChannelPlaylist.ID) -> ChannelPlaylist? {
logger.info("RETRIEVE \(playlistCacheKey(id))")
if let json = try? storage.object(forKey: playlistCacheKey(id)).dictionaryValue["playlist"] {
if let json = try? storage?.object(forKey: playlistCacheKey(id)).dictionaryValue["playlist"] {
return ChannelPlaylist.from(json)
}
@@ -36,9 +36,9 @@ struct ChannelPlaylistsCacheModel {
}
func getPlaylistsTime(_ id: ChannelPlaylist.ID) -> Date? {
if let json = try? storage.object(forKey: playlistTimeCacheKey(id)),
if let json = try? storage?.object(forKey: playlistTimeCacheKey(id)),
let string = json.dictionaryValue["date"]?.string,
let date = CacheModel.shared.iso8601DateFormatter.date(from: string)
let date = iso8601DateFormatter.date(from: string)
{
return date
}
@@ -47,17 +47,7 @@ struct ChannelPlaylistsCacheModel {
}
func getFormattedPlaylistTime(_ id: ChannelPlaylist.ID) -> String {
if let time = getPlaylistsTime(id) {
let isSameDay = Calendar(identifier: .iso8601).isDate(time, inSameDayAs: Date())
let formatter = isSameDay ? CacheModel.shared.dateFormatterForTimeOnly : CacheModel.shared.dateFormatter
return formatter.string(from: time)
}
return ""
}
func clear() {
try? storage.removeAll()
getFormattedDate(getPlaylistsTime(id))
}
private func playlistCacheKey(_ playlist: ChannelPlaylist.ID) -> String {

View File

@@ -3,7 +3,7 @@ import Foundation
import Logging
import SwiftyJSON
struct FeedCacheModel {
struct FeedCacheModel: CacheModel {
static let shared = FeedCacheModel()
static let limit = 30
let logger = Logger(label: "stream.yattee.cache.feed")
@@ -11,25 +11,25 @@ struct FeedCacheModel {
static let diskConfig = DiskConfig(name: "feed")
static let memoryConfig = MemoryConfig()
let storage = try! Storage<String, JSON>(
let storage = try? Storage<String, JSON>(
diskConfig: Self.diskConfig,
memoryConfig: Self.memoryConfig,
transformer: CacheModel.jsonTransformer
transformer: BaseCacheModel.jsonTransformer
)
func storeFeed(account: Account, videos: [Video]) {
let date = CacheModel.shared.iso8601DateFormatter.string(from: Date())
let date = iso8601DateFormatter.string(from: Date())
logger.info("caching feed \(account.feedCacheKey) -- \(date)")
let feedTimeObject: JSON = ["date": date]
let videosObject: JSON = ["videos": videos.prefix(Self.limit).map { $0.json.object }]
try? storage.setObject(feedTimeObject, forKey: feedTimeCacheKey(account.feedCacheKey))
try? storage.setObject(videosObject, forKey: account.feedCacheKey)
try? storage?.setObject(feedTimeObject, forKey: feedTimeCacheKey(account.feedCacheKey))
try? storage?.setObject(videosObject, forKey: account.feedCacheKey)
}
func retrieveFeed(account: Account) -> [Video] {
logger.info("retrieving cache for \(account.feedCacheKey)")
if let json = try? storage.object(forKey: account.feedCacheKey),
if let json = try? storage?.object(forKey: account.feedCacheKey),
let videos = json.dictionaryValue["videos"]
{
return videos.arrayValue.map { Video.from($0) }
@@ -39,9 +39,9 @@ struct FeedCacheModel {
}
func getFeedTime(account: Account) -> Date? {
if let json = try? storage.object(forKey: feedTimeCacheKey(account.feedCacheKey)),
if let json = try? storage?.object(forKey: feedTimeCacheKey(account.feedCacheKey)),
let string = json.dictionaryValue["date"]?.string,
let date = CacheModel.shared.iso8601DateFormatter.date(from: string)
let date = iso8601DateFormatter.date(from: string)
{
return date
}
@@ -49,10 +49,6 @@ struct FeedCacheModel {
return nil
}
func clear() {
try? storage.removeAll()
}
private func feedTimeCacheKey(_ feedCacheKey: String) -> String {
"\(feedCacheKey)-feedTime"
}

View File

@@ -3,7 +3,7 @@ import Foundation
import Logging
import SwiftyJSON
struct PlaylistsCacheModel {
struct PlaylistsCacheModel: CacheModel {
static let shared = PlaylistsCacheModel()
static let limit = 30
let logger = Logger(label: "stream.yattee.cache.playlists")
@@ -11,25 +11,25 @@ struct PlaylistsCacheModel {
static let diskConfig = DiskConfig(name: "playlists")
static let memoryConfig = MemoryConfig()
let storage = try! Storage<String, JSON>(
let storage = try? Storage<String, JSON>(
diskConfig: Self.diskConfig,
memoryConfig: Self.memoryConfig,
transformer: CacheModel.jsonTransformer
transformer: BaseCacheModel.jsonTransformer
)
func storePlaylist(account: Account, playlists: [Playlist]) {
let date = CacheModel.shared.iso8601DateFormatter.string(from: Date())
let date = iso8601DateFormatter.string(from: Date())
logger.info("caching \(playlistCacheKey(account)) -- \(date)")
let feedTimeObject: JSON = ["date": date]
let playlistsObject: JSON = ["playlists": playlists.map { $0.json.object }]
try? storage.setObject(feedTimeObject, forKey: playlistTimeCacheKey(account))
try? storage.setObject(playlistsObject, forKey: playlistCacheKey(account))
try? storage?.setObject(feedTimeObject, forKey: playlistTimeCacheKey(account))
try? storage?.setObject(playlistsObject, forKey: playlistCacheKey(account))
}
func retrievePlaylists(account: Account) -> [Playlist] {
logger.info("retrieving cache for \(playlistCacheKey(account))")
if let json = try? storage.object(forKey: playlistCacheKey(account)),
if let json = try? storage?.object(forKey: playlistCacheKey(account)),
let playlists = json.dictionaryValue["playlists"]
{
return playlists.arrayValue.map { Playlist.from($0) }
@@ -39,9 +39,9 @@ struct PlaylistsCacheModel {
}
func getPlaylistsTime(account: Account) -> Date? {
if let json = try? storage.object(forKey: playlistTimeCacheKey(account)),
if let json = try? storage?.object(forKey: playlistTimeCacheKey(account)),
let string = json.dictionaryValue["date"]?.string,
let date = CacheModel.shared.iso8601DateFormatter.date(from: string)
let date = iso8601DateFormatter.date(from: string)
{
return date
}
@@ -50,17 +50,7 @@ struct PlaylistsCacheModel {
}
func getFormattedPlaylistTime(account: Account) -> String {
if let time = getPlaylistsTime(account: account) {
let isSameDay = Calendar(identifier: .iso8601).isDate(time, inSameDayAs: Date())
let formatter = isSameDay ? CacheModel.shared.dateFormatterForTimeOnly : CacheModel.shared.dateFormatter
return formatter.string(from: time)
}
return ""
}
func clear() {
try? storage.removeAll()
getFormattedDate(getPlaylistsTime(account: account))
}
private func playlistCacheKey(_ account: Account) -> String {

View File

@@ -5,17 +5,17 @@ import Siesta
import SwiftUI
import SwiftyJSON
final class SubscribedChannelsModel: ObservableObject {
final class SubscribedChannelsModel: ObservableObject, CacheModel {
static var shared = SubscribedChannelsModel()
let logger = Logger(label: "stream.yattee.cache.channels")
static let diskConfig = DiskConfig(name: "channels")
static let memoryConfig = MemoryConfig()
let storage = try! Storage<String, JSON>(
let storage = try? Storage<String, JSON>(
diskConfig: SubscribedChannelsModel.diskConfig,
memoryConfig: SubscribedChannelsModel.memoryConfig,
transformer: CacheModel.jsonTransformer
transformer: BaseCacheModel.jsonTransformer
)
@Published var isLoading = false
@@ -89,20 +89,20 @@ final class SubscribedChannelsModel: ObservableObject {
}
func storeChannels(account: Account, channels: [Channel]) {
let date = CacheModel.shared.iso8601DateFormatter.string(from: Date())
let date = iso8601DateFormatter.string(from: Date())
logger.info("caching channels \(channelsDateCacheKey(account)) -- \(date)")
let dateObject: JSON = ["date": date]
let channelsObject: JSON = ["channels": channels.map(\.json).map(\.object)]
try? storage.setObject(dateObject, forKey: channelsDateCacheKey(account))
try? storage.setObject(channelsObject, forKey: channelsCacheKey(account))
try? storage?.setObject(dateObject, forKey: channelsDateCacheKey(account))
try? storage?.setObject(channelsObject, forKey: channelsCacheKey(account))
}
func getChannels(account: Account) -> [Channel] {
logger.info("getting channels \(channelsDateCacheKey(account))")
if let json = try? storage.object(forKey: channelsCacheKey(account)),
if let json = try? storage?.object(forKey: channelsCacheKey(account)),
let channels = json.dictionaryValue["channels"]
{
return channels.arrayValue.map { Channel.from($0) }
@@ -125,10 +125,10 @@ final class SubscribedChannelsModel: ObservableObject {
"channels-\(account.id)-date"
}
func getFeedTime(account: Account) -> Date? {
if let json = try? storage.object(forKey: channelsDateCacheKey(account)),
func getChannelsTime(account: Account) -> Date? {
if let json = try? storage?.object(forKey: channelsDateCacheKey(account)),
let string = json.dictionaryValue["date"]?.string,
let date = CacheModel.shared.iso8601DateFormatter.date(from: string)
let date = iso8601DateFormatter.date(from: string)
{
return date
}
@@ -136,21 +136,15 @@ final class SubscribedChannelsModel: ObservableObject {
return nil
}
var feedTime: Date? {
var channelsTime: Date? {
if let account = accounts.current {
return getFeedTime(account: account)
return getChannelsTime(account: account)
}
return nil
}
var formattedCacheTime: String {
if let feedTime {
let isSameDay = Calendar(identifier: .iso8601).isDate(feedTime, inSameDayAs: Date())
let formatter = isSameDay ? CacheModel.shared.dateFormatterForTimeOnly : CacheModel.shared.dateFormatter
return formatter.string(from: feedTime)
}
return ""
getFormattedDate(channelsTime)
}
}

View File

@@ -3,35 +3,31 @@ import Foundation
import Logging
import SwiftyJSON
struct VideosCacheModel {
struct VideosCacheModel: CacheModel {
static let shared = VideosCacheModel()
let logger = Logger(label: "stream.yattee.cache.videos")
static let diskConfig = DiskConfig(name: "videos")
static let memoryConfig = MemoryConfig()
let storage = try! Storage<String, JSON>(
let storage = try? Storage<String, JSON>(
diskConfig: Self.diskConfig,
memoryConfig: Self.memoryConfig,
transformer: CacheModel.jsonTransformer
transformer: BaseCacheModel.jsonTransformer
)
func storeVideo(_ video: Video) {
logger.info("caching \(video.cacheKey)")
try? storage.setObject(video.json, forKey: video.cacheKey)
try? storage?.setObject(video.json, forKey: video.cacheKey)
}
func retrieveVideo(_ cacheKey: String) -> Video? {
logger.info("retrieving cache for \(cacheKey)")
if let json = try? storage.object(forKey: cacheKey) {
if let json = try? storage?.object(forKey: cacheKey) {
return Video.from(json)
}
return nil
}
func clear() {
try? storage.removeAll()
}
}

View File

@@ -1,7 +1,9 @@
import Cache
import Foundation
import Siesta
import SwiftyJSON
final class FeedModel: ObservableObject {
final class FeedModel: ObservableObject, CacheModel {
static let shared = FeedModel()
@Published var isLoading = false
@@ -10,6 +12,8 @@ final class FeedModel: ObservableObject {
private var accounts = AccountsModel.shared
var storage: Storage<String, JSON>?
var feed: Resource? {
accounts.api.feed(page)
}
@@ -104,13 +108,7 @@ final class FeedModel: ObservableObject {
}
var formattedFeedTime: String {
if let feedTime {
let isSameDay = Calendar(identifier: .iso8601).isDate(feedTime, inSameDayAs: Date())
let formatter = isSameDay ? CacheModel.shared.dateFormatterForTimeOnly : CacheModel.shared.dateFormatter
return formatter.string(from: feedTime)
}
return ""
getFormattedDate(feedTime)
}
private func loadCachedFeed() {