davbeck/PersistentCacheKit
A Swift package for caching items to the filesystem (using SQLite by default).
Usage
struct Message: Codable {
var id: UUID = UUID()
var createdAt: Date = Date()
var body: String = ""
}
let cache = PersistentCache<UUID, [Message]>()
let roomID = UUID()
if let cached = cache[roomID] {
// show cached messages
} else {
// load them some expensive way
cache[roomID] = (0..<10).map({ Message(body: String($0)) })
}Creating a cache:
Often you only need to specify the key and value types. However you can also include a cache storage and namespace:
let cache = PersistentCache<UUID, [Message]>(storage: customStorage, namespace: "com.example.app")Using custom storage can be useful either to use a different storage method or to parallize storage between caches.
A namespace is very useful to avoid name collisions between multiple caches.
Access values
The simplest way to access cache data is to use subscripts.
let value = cache[key]
cache[key] = valueThis will use the memory cache if possible, or access storage if needed.
You can also access data using cache items:
let value = cache[item: key]
cache[item: key] = Item(value, expiresIn: 60 * 60)This is mostly valuable to set an expiration date for the value. Regular subscript will ignore an expired item, so in practice it should be rare that you need to get an item directly.
Various fetch metohds exist to do a find or update on the cache:
cache.fetch(key, fallback: { value })This is a basic wrapper around subscript access. The other fetch methods perform lookup asynchronously:
cache.fetch(key, queue: .main) { value in
// use value (possibly nil)
}
cache.fetch(key, queue: .main, fallback: { value }) { value in
// use value (never nil)
}These methods will first check the memory cache for data and if present, call completion immediately without dispatching to another thread. However if needed, they will asynchronously load data from storage on a background queue.
Patterns
It can be a good idea for testing and flexibility to have your cache passed in on creation:
class Foo {
let cache: PersistentCache<UUID, String>?
init(cache: PersistentCache<UUID, String>? = PersistentCache(namespace: "Foo")) {
self.cache = cache
}
}
let fooA = Foo(cache: PersistentCache(storage: custom))
let fooA = Foo(cache: PersistentCache(storage: nil))
let fooB = Foo(cache: nil)Notice that the cache is optional. If a test or a user of a framework wants to disable caching completely they can pass nil for the cache. Or to disable persistent storage and only use in memory caching, they can pass in a cache with no backing storage. And finally, if they want to use a custom storage method, they can pass in a cache with their specific storage class.
Package Metadata
Repository: davbeck/PersistentCacheKit
Stars: 7
Forks: 2
Open issues: 0
Default branch: master
Primary language: swift
License: MIT
README: README.md