Skip to content

Commit

Permalink
Accept that Metrics can’t be cached
Browse files Browse the repository at this point in the history
Not decodable to Storage of iOS-Cache
  • Loading branch information
maerki committed May 9, 2024
1 parent c5896ec commit c1a85b8
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 28 deletions.
19 changes: 6 additions & 13 deletions Sources/UBFoundation/Networking/BaseCachingLogic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ open class UBBaseCachingLogic: UBCachingLogic {
/// The quality of service
public let qos: DispatchQoS

private let UserInfoKeyMetrics = "UserInfoKeyMetrics"
private let UserInfoKeyMethod = "UserInfoKeyMethod"

private let UserInfoKeyAcceptLanguage = "Accept-Language"
Expand Down Expand Up @@ -138,9 +137,6 @@ open class UBBaseCachingLogic: UBCachingLogic {

// If successful then cache the data
var userInfo = [AnyHashable: Any]()
if let metrics = metrics {
// userInfo[UserInfoKeyMetrics] = metrics
}
if let headers = request.allHTTPHeaderFields,
let acceptHeader = headers.getCaseInsensitiveValue(key: acceptedLanguageHeaderFieldName) {
userInfo[UserInfoKeyAcceptLanguage] = acceptHeader
Expand Down Expand Up @@ -193,9 +189,6 @@ open class UBBaseCachingLogic: UBCachingLogic {
return .miss
}

// Load metrics from last request
let metrics = cachedResponse.userInfo?[UserInfoKeyMetrics] as? URLSessionTaskMetrics

// Setup reload headers
var reloadHeaders: [String: String] = [:]
if let lastModified = response.ub_getHeaderField(key: lastModifiedHeaderFieldName) {
Expand All @@ -205,7 +198,7 @@ open class UBBaseCachingLogic: UBCachingLogic {
reloadHeaders[ifNoneMatchHeaderFieldName] = etag
}

let possibleResult = UBCacheResult.hit(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders, metrics: metrics)
let possibleResult = UBCacheResult.hit(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders)

if let cacheControlHeader = response.ub_getHeaderField(key: cacheControlHeaderFieldName),
let cacheControlDirectives = UBCacheResponseDirectives(cacheControlHeader: cacheControlHeader) {
Expand Down Expand Up @@ -238,24 +231,24 @@ open class UBBaseCachingLogic: UBCachingLogic {
if cacheAge < 0 {
return modifyCacheResult(proposed: .miss, possible: possibleResult, reason: .negativeCacheAge(cacheAge: cacheAge))
} else if cacheAge > maxAge {
return modifyCacheResult(proposed: .expired(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders, metrics: metrics), possible: possibleResult, reason: .cacheAgeOlderMax(cacheAge: cacheAge, maxAge: maxAge))
return modifyCacheResult(proposed: .expired(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders), possible: possibleResult, reason: .cacheAgeOlderMax(cacheAge: cacheAge, maxAge: maxAge))
} else {
return modifyCacheResult(proposed: .hit(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders, metrics: metrics), possible: possibleResult, reason: .cacheAgeYoungerMax(cacheAge: cacheAge, maxAge: maxAge))
return modifyCacheResult(proposed: .hit(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders), possible: possibleResult, reason: .cacheAgeYoungerMax(cacheAge: cacheAge, maxAge: maxAge))
}

// If there are no max age then search for expire header
} else if let expiresHeader = response.ub_getHeaderField(key: expiresHeaderFieldName),
let expiresDate = dateFormatter.date(from: expiresHeader) {
if expiresDate < Date() {
return modifyCacheResult(proposed: .expired(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders, metrics: metrics), possible: possibleResult, reason: .expiredInPast(expiresDate: expiresDate))
return modifyCacheResult(proposed: .expired(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders), possible: possibleResult, reason: .expiredInPast(expiresDate: expiresDate))
} else {
return modifyCacheResult(proposed: .hit(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders, metrics: metrics), possible: possibleResult, reason: .expiresInFuture(expiresDate: expiresDate))
return modifyCacheResult(proposed: .hit(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders), possible: possibleResult, reason: .expiresInFuture(expiresDate: expiresDate))
}

// If there is no max age neither expires, don't cache
} else if let responseDateHearder = response.ub_getHeaderField(key: dateHeaderFieldName), let responseDate = dateFormatter.date(from: responseDateHearder) {
// We could do heuristic caching, but behaviour could be unexpected
return modifyCacheResult(proposed: .expired(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders, metrics: metrics), possible: possibleResult, reason: .noCacheHeaders)
return modifyCacheResult(proposed: .expired(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders), possible: possibleResult, reason: .noCacheHeaders)

// In case no caching information is found just remove the cached object
} else {
Expand Down
12 changes: 6 additions & 6 deletions Sources/UBFoundation/Networking/CachingLogic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@ public enum UBCacheResult {
/// The cache missed
case miss
/// Cached data found but is expired
case expired(cachedResponse: CachedURLResponse, reloadHeaders: [String: String], metrics: URLSessionTaskMetrics?)
case expired(cachedResponse: CachedURLResponse, reloadHeaders: [String: String])
/// Cached data found and is valid
case hit(cachedResponse: CachedURLResponse, reloadHeaders: [String: String], metrics: URLSessionTaskMetrics?)
case hit(cachedResponse: CachedURLResponse, reloadHeaders: [String: String])

var reloadHeaders: [String: String] {
switch self {
case .miss: return [:]
case .expired(cachedResponse: _, reloadHeaders: let h, metrics: _): return h
case .hit(cachedResponse: _, reloadHeaders: let h, metrics: _): return h
case .expired(cachedResponse: _, reloadHeaders: let h): return h
case .hit(cachedResponse: _, reloadHeaders: let h): return h
}
}

var cachedResponse: CachedURLResponse? {
switch self {
case .miss: return nil
case .expired(cachedResponse: let r, reloadHeaders: _, metrics: _): return r
case .hit(cachedResponse: let r, reloadHeaders: _, metrics: _): return r
case .expired(cachedResponse: let r, reloadHeaders: _): return r
case .hit(cachedResponse: let r, reloadHeaders: _): return r
}
}
}
Expand Down
18 changes: 9 additions & 9 deletions Sources/UBFoundation/Networking/UBURLSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ public class UBURLSession: UBDataTaskURLSession {
}
return createTask(request.getRequest())

case let (.useProtocolCachePolicy, .hit(cachedResponse: cachedResponse, reloadHeaders: _, metrics: metrics)),
let (.returnCacheDataDontLoad, .hit(cachedResponse: cachedResponse, reloadHeaders: _, metrics: metrics)),
let (.returnCacheDataElseLoad, .hit(cachedResponse: cachedResponse, reloadHeaders: _, metrics: metrics)),
let (.returnCacheDataElseLoad, .expired(cachedResponse: cachedResponse, reloadHeaders: _, metrics: metrics)):
case let (.useProtocolCachePolicy, .hit(cachedResponse: cachedResponse, reloadHeaders: _)),
let (.returnCacheDataDontLoad, .hit(cachedResponse: cachedResponse, reloadHeaders: _)),
let (.returnCacheDataElseLoad, .hit(cachedResponse: cachedResponse, reloadHeaders: _)),
let (.returnCacheDataElseLoad, .expired(cachedResponse: cachedResponse, reloadHeaders: _)):
#if os(watchOS)
let info = UBNetworkingTaskInfo(cacheHit: true, refresh: false)
#else
Expand All @@ -89,22 +89,22 @@ public class UBURLSession: UBDataTaskURLSession {
owner.dataTaskCompleted(data: cachedResponse.data, response: cachedResponse.response as? HTTPURLResponse, error: nil, info: info)
owner.completionHandlersDispatchQueue.sync {
if let cachedResponse = cachedResponse.response as? HTTPURLResponse {
sessionDelegate.cachingLogic?.hasUsed(cachedResponse: cachedResponse, nonModifiedResponse: nil, metrics: metrics, request: request.getRequest(), dataTask: owner)
sessionDelegate.cachingLogic?.hasUsed(cachedResponse: cachedResponse, nonModifiedResponse: nil, metrics: nil, request: request.getRequest(), dataTask: owner)
}
}
return nil

case (.returnCacheDataDontLoad, .expired(cachedResponse: _, reloadHeaders: _, metrics: _)),
case (.returnCacheDataDontLoad, .expired(cachedResponse: _, reloadHeaders: _)),
(.returnCacheDataDontLoad, .miss):
sessionDelegate.cachingLogic?.hasMissedCache(dataTask: owner)
owner.completionHandlersDispatchQueue.sync {
owner.dataTaskCompleted(data: nil, response: nil, error: UBInternalNetworkingError.noCachedData, info: nil)
}
return nil

case let (.useProtocolCachePolicy, .expired(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders, metrics: _)),
let (.reloadRevalidatingCacheData, .expired(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders, metrics: _)),
let (.reloadRevalidatingCacheData, .hit(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders, metrics: _)):
case let (.useProtocolCachePolicy, .expired(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders)),
let (.reloadRevalidatingCacheData, .expired(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders)),
let (.reloadRevalidatingCacheData, .hit(cachedResponse: cachedResponse, reloadHeaders: reloadHeaders)):
var reloadRequest = request.getRequest()
for header in reloadHeaders {
reloadRequest.setValue(header.value, forHTTPHeaderField: header.key)
Expand Down

0 comments on commit c1a85b8

Please sign in to comment.