Created
February 11, 2019 12:47
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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