Clean up DownloadWithCacheManager’s cache at most every five minutes — it’s very expensive to do it on every request. This dramatically helps sidebar scrolling performance when you have a couple thousand feeds all trying to get their favicons.
This commit is contained in:
parent
e6dee88e2e
commit
b04876185d
@ -65,11 +65,6 @@ private struct WebCacheRecord {
|
||||
let dateDownloaded: Date
|
||||
let data: Data
|
||||
let response: URLResponse
|
||||
|
||||
func isExpired(_ timeToLive: TimeInterval) -> Bool {
|
||||
|
||||
return Date().timeIntervalSince(dateDownloaded) > timeToLive
|
||||
}
|
||||
}
|
||||
|
||||
private final class WebCache {
|
||||
@ -77,18 +72,19 @@ private final class WebCache {
|
||||
private var cache = [URL: WebCacheRecord]()
|
||||
|
||||
func cleanup(_ cleanupInterval: TimeInterval) {
|
||||
|
||||
|
||||
let cutoffDate = Date(timeInterval: -cleanupInterval, since: Date())
|
||||
cache.keys.forEach { (key) in
|
||||
let cacheRecord = self[key]!
|
||||
if shouldDelete(cacheRecord, cleanupInterval) {
|
||||
if shouldDelete(cacheRecord, cutoffDate) {
|
||||
cache[key] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func shouldDelete(_ cacheRecord: WebCacheRecord, _ cleanupInterval: TimeInterval) -> Bool {
|
||||
private func shouldDelete(_ cacheRecord: WebCacheRecord, _ cutoffDate: Date) -> Bool {
|
||||
|
||||
return Date().timeIntervalSince(cacheRecord.dateDownloaded) > cleanupInterval
|
||||
return cacheRecord.dateDownloaded < cutoffDate
|
||||
}
|
||||
|
||||
subscript(_ url: URL) -> WebCacheRecord? {
|
||||
@ -115,26 +111,24 @@ private final class DownloadWithCacheManager {
|
||||
static let shared = DownloadWithCacheManager()
|
||||
private var cache = WebCache()
|
||||
private static let timeToLive: TimeInterval = 10 * 60 // 10 minutes
|
||||
private static let cleanupInterval: TimeInterval = 30 * 60 // 30 minutes
|
||||
private static let cleanupInterval: TimeInterval = 5 * 60 // clean up the cache at most every 5 minutes
|
||||
private var lastCleanupDate = Date()
|
||||
|
||||
func download(_ url: URL, _ callback: @escaping OneShotDownloadCallback) {
|
||||
|
||||
cache.cleanup(DownloadWithCacheManager.cleanupInterval)
|
||||
if lastCleanupDate.timeIntervalSinceNow < -(5 * 60) {
|
||||
lastCleanupDate = Date()
|
||||
cache.cleanup(DownloadWithCacheManager.timeToLive)
|
||||
}
|
||||
|
||||
let cacheRecord: WebCacheRecord? = cache[url]
|
||||
if let cacheRecord = cacheRecord, !cacheRecord.isExpired(DownloadWithCacheManager.timeToLive) {
|
||||
if let cacheRecord = cacheRecord {
|
||||
callback(cacheRecord.data, cacheRecord.response, nil)
|
||||
return
|
||||
}
|
||||
|
||||
OneShotDownloadManager.shared.download(url) { (data, response, error) in
|
||||
|
||||
if let _ = error, let cacheRecord = cacheRecord {
|
||||
// In the case where a cache record has expired, but the download returned an error, we use the cache record anyway. By design.
|
||||
callback(cacheRecord.data, cacheRecord.response, nil)
|
||||
return
|
||||
}
|
||||
|
||||
if let data = data, let response = response, response.statusIsOK, error == nil {
|
||||
let cacheRecord = WebCacheRecord(url: url, dateDownloaded: Date(), data: data, response: response)
|
||||
self.cache[url] = cacheRecord
|
||||
|
Loading…
x
Reference in New Issue
Block a user