Lightweight key-value store with Structured Concurrency API
Lightweight key-value store with Structured Concurrency API.
If your app is built with Swift Concurrency and is in need for a lightweight key-value storage solution, swift-filestore
should be a good fit.
It is a key-value persistence solution which provides CRUD operation and change stream APIs under Swift’s Structured Concurrency(async/await
, AsyncSequence
).
Under the hood it simply serializes each object into a separate file, no databases or caches solutions are involved. This keeps your app lean and stable.
Obtain an instance by calling FileObjectStore.create()
. The method simply create a root directory under app’s Application Support
directory.
In rare cases where it fails to create the directory, you can choose to fallback to a in-memory implementation of ObjectStore
, or can handle it in your own way.
func createWithFallback() -> ObjectStore {
do {
return try FileObjectStore.create()
} catch {
return MemoryObjectStore()
}
}
swift-filestore
does not require developers to create new struct/classes for your data model. For example, to use JSON serialization, just have your existing model conform to JSONDataRepresentable
.
struct MyModel: Codable, JSONDataRepresentable {
let id: String
let value: String
}
let model = MyModel()
try await objectStore.write(key: model.id, namespace: "MyModels", object: model)
swift-filestore
offers an object change subscription API via Swift Concurrency.
for try await model in await objectStore.observe(key: id, namespace: "MyModels", objectType: MyModel.self) {
// process the newly emitted model object
}
If you are looking for non-json serializations, you can define your custom serialization/deserialization protocol as below:
protocol BinaryDataRepresentable: DataRepresentable {}
extension BinaryDataRepresentable {
public func serialize() throws -> Data {
// your custom serialization goes here...
}
public static func from(data: Data) throws -> Self {
// your custom deseriazation goes here...
}
}
struct MyModel: BinaryDataRepresentable {
let id: String
let value: String
}
swift-filestore
offers an immutable logging component named PersistenceLog
. It allows developer to store records on the disk and flush them at the right time. It can be used as an alternative to in-memory logging, which may risk data loss because app can be terminated at any time by user or the system.
Below code demonstrates how to use PersistenceLog
to store and send in-app analytic events:
//data model for the analytics log
struct AnalyticsEvent: Codable, JSONDataRepresentable {
let name: String
let metaData: String
}
//initialization
let log = try PersistenceLogImpl<AnalyticsEvent>(name: "analytics-log")
//When new event is triggered
try await log.append(event1)
//When it's time to flush and sent to remote server
let events = try await log.flush()
try await networkClient.sendAnalytics(events)