Skip to content

Instantly share code, notes, and snippets.

@muzahid59
Created February 11, 2019 12:47
Show Gist options
  • Select an option

  • Save muzahid59/05f8d687b0707545609f7ae4e2a30b0f to your computer and use it in GitHub Desktop.

Select an option

Save muzahid59/05f8d687b0707545609f7ae4e2a30b0f to your computer and use it in GitHub Desktop.
Basic idea: * Get value of a give context if exist at current version. * If the value locally not found then fetch from repository and save as current version. * Resolver gives the options which version we want. Old one or new one or both.
struct Version<ContextType, ValueType> {
let context: ContextType
let value: ValueType
}
class SingleCache<ContextType, ValueType> {
typealias CacheVersion = Version<ContextType, ValueType>
typealias CompletionHandler = (_ oldValue: CacheVersion?, _ newValue: CacheVersion?) -> ()
typealias FetchCompletionHandler = (ValueType?)->()
var curVersion: CacheVersion?
let fetcher: (_ context: ContextType, _ completion: @escaping FetchCompletionHandler) -> ()
let equalityChecker: (ContextType, ContextType) -> Bool
let resolver: (_ oldVersion: CacheVersion?, _ newVersion: CacheVersion?) -> CacheVersion?
init(fetcher: @escaping (_ context: ContextType, _ completion: @escaping FetchCompletionHandler) -> (),
equalityChecker: @escaping (ContextType, ContextType) -> Bool,
resolver: @escaping (_ oldVersion: CacheVersion?, _ newVersion: CacheVersion?) -> CacheVersion? = { $1 }) {
self.fetcher = fetcher
self.equalityChecker = equalityChecker
self.resolver = resolver
}
private func fetchAndReturn(for context: ContextType, completion: @escaping CompletionHandler) {
fetcher(context) { [weak self] newValue in
guard let `self` = self else { completion(nil, nil); return }
let oldVersion = self.curVersion
let newVersion: CacheVersion?
if let value = newValue {
newVersion = Version(context: context, value: value)
} else {
newVersion = nil
}
self.curVersion = self.resolver(oldVersion, newVersion)
completion(oldVersion, newVersion)
}
}
func get(for context: ContextType, completion: @escaping CompletionHandler) {
if let version = curVersion, equalityChecker(context, version.context) {
completion(version, version)
} else {
fetchAndReturn(for: context, completion: completion)
}
}
}
/// Testing
let dump: [String: [String]] = [
"ios": ["Ashik", "Dulal", "Muzahid"],
"android": ["Sourav"]
]
let cache = SingleCache<String, [String]>(
fetcher: { (context, completion) in
print("fetching ...")
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1, execute: {
completion(dump[context])
})
},
equalityChecker: { (oldStr, newStr) -> Bool in
return oldStr == newStr
})
cache.get(for: "ios") {
print($1?.value)
cache.get(for: "ios") {
print($1?.value)
cache.get(for: "android") {
print($0?.value, $1?.value)
print(cache.curVersion)
cache.curVersion = Version(context: "backend", value: ["rinku", "masum"])
cache.get(for: "backend") {
print($0, $1)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment