Adds documentation

multistore
Laurent 1 year ago
parent 59f85f998b
commit df7b1461a7
  1. 21
      LeStorage/Store.swift
  2. 16
      LeStorage/StoredCollection.swift
  3. 8
      LeStorage/StoredSingleton.swift

@ -26,8 +26,6 @@ public class Store {
/// The Store singleton
public static let main = Store()
// public fileprivate(set) var currentUser: User? = nil
/// A method to provide ids corresponding to the django storage
public static func randomId() -> String {
return UUID().uuidString.lowercased()
@ -81,16 +79,10 @@ public class Store {
let collection = StoredCollection<T>(synchronized: synchronized, store: Store.main, indexed: indexed, inMemory: inMemory, sendsUpdate: sendsUpdate, loadCompletion: nil)
self._collections[T.resourceName()] = collection
// if synchronized { // register additional collection for api calls
// let apiCallCollection = StoredCollection<ApiCall<T>>(synchronized: false, store: Store.main, loadCompletion: { apiCallCollection in
// self._rescheduleCalls(collection: apiCallCollection)
// })
// self._apiCallsCollections[T.resourceName()] = apiCallCollection
// }
return collection
}
/// Registers a StoredSingleton instance
public func registerObject<T : Storable>(synchronized: Bool, inMemory: Bool = false, sendsUpdate: Bool = true) -> StoredSingleton<T> {
// register collection
@ -102,12 +94,14 @@ public class Store {
// MARK: - Settings
/// Stores the user UUID
func setUserUUID(uuidString: String) {
self._settingsStorage.update { settings in
settings.userId = uuidString
}
}
/// Returns the user's UUID
public var currentUserUUID: UUID? {
if let uuidString = self._settingsStorage.item.userId,
let uuid = UUID(uuidString: uuidString) {
@ -116,6 +110,7 @@ public class Store {
return nil
}
/// Returns a UUID, using the user's if possible
public func mandatoryUserUUID() -> UUID {
if let uuid = self.currentUserUUID {
return uuid
@ -128,16 +123,19 @@ public class Store {
}
}
/// Returns the username
func userName() -> String? {
return self._settingsStorage.item.username
}
/// Sets the username
func setUserName(_ username: String) {
self._settingsStorage.update { settings in
settings.username = username
}
}
/// Disconnect the user from the storage and resets collection
public func disconnect(resetOption: ResetOption? = nil) {
try? self.service().disconnect()
self._settingsStorage.update { settings in
@ -162,6 +160,7 @@ public class Store {
}
/// Returns whether the system has a user token
public func hasToken() -> Bool {
do {
_ = try self.service().keychainStore.getToken()
@ -229,6 +228,7 @@ public class Store {
return try await self.service().runApiCall(apiCall)
}
/// Executes an API call
func execute<T>(apiCall: ApiCall<T>) async throws -> T {
return try await self._executeApiCall(apiCall)
}
@ -240,12 +240,14 @@ public class Store {
return try await self.service().get()
}
/// Resets all registered collection
public func reset() {
for collection in self._collections.values {
collection.reset()
}
}
/// Loads all collection with the data from the server
public func loadCollectionFromServer() {
for collection in self._collections.values {
Task {
@ -254,6 +256,7 @@ public class Store {
}
}
/// Returns whether any collection has pending API calls
public func hasPendingAPICalls() -> Bool {
return self._collections.values.contains(where: { $0.hasPendingAPICalls() })
}

@ -132,8 +132,8 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
}
/// Starts the JSON file decoding synchronously or asynchronously
fileprivate func _loadFromFile() throws {
// let url: URL = try self._urlForJSONFile()
if self.asynchronousIO {
Task(priority: .high) {
@ -214,6 +214,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
}
/// A method the treat the collection as a single instance holder
func setSingletonNoSync(instance: T) {
defer {
self._hasChanged = true
@ -251,6 +252,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
}
}
/// Adds or update a sequence of elements
public func addOrUpdate(contentOfs sequence: any Sequence<T>) throws {
try self._addOrUpdate(contentOfs: sequence)
}
@ -310,6 +312,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
}
/// Proceeds to delete all instance of the collection, properly cleaning up dependencies and sending API calls
public func deleteAll() throws {
try self.delete(contentOfs: self.items)
}
@ -350,10 +353,12 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
Logger.log("End write")
}
/// Simply clears the items of the collection
func clear() {
self.items.removeAll()
}
/// Removes the items of the collection, deletes the corresponding file, and also reset the related API calls collection
public func reset() {
self.items.removeAll()
@ -373,6 +378,8 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
// MARK: - Synchronization
/// Returns an APICall instance for the Storable [instance] and an HTTP [method]
/// The method updates existing calls or creates a new one
fileprivate func _callForInstance(_ instance: T, method: HTTPMethod) throws -> ApiCall<T>? {
guard let apiCallCollection = self.apiCallsCollection else {
throw StoredCollectionError.missingApiCallCollection
@ -395,6 +402,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
}
}
/// Creates an API call for the Storable [instance] and an HTTP [method]
fileprivate func _createCall(_ instance: T, method: HTTPMethod) throws -> ApiCall<T> {
let baseURL = try _store.service().baseURL
let jsonString = try instance.jsonString()
@ -410,6 +418,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
return ApiCall(url: url, method: method.rawValue, dataId: String(instance.id), body: jsonString)
}
/// Prepares a call for execution by updating its properties and adding it to its collection for storage
fileprivate func _prepareCall(apiCall: ApiCall<T>) throws {
apiCall.lastAttemptDate = Date()
apiCall.attemptsCount += 1
@ -488,14 +497,15 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
/// Indicates if the collection is currently retrying ApiCalls
fileprivate var _isRetryingCalls: Bool = false
/// Reschedule API calls if necessary
func rescheduleApiCallsIfNecessary() {
if !self._isRetryingCalls {
self._rescheduleApiCalls()
}
}
/// Reschedule API calls
fileprivate func _rescheduleApiCalls() {
// return
guard let apiCallsCollection, apiCallsCollection.isNotEmpty else {
return
@ -532,6 +542,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
}
/// Deletes an API call by [id]
func deleteApiCallById(_ id: String) throws {
guard let apiCallsCollection else {
throw StoreError.apiCallCollectionNotRegistered(type: T.resourceName())
@ -539,6 +550,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
try apiCallsCollection.deleteById(id)
}
/// Returns if the API call collection is not empty
func hasPendingAPICalls() -> Bool {
guard let apiCallsCollection else { return false }
return apiCallsCollection.isNotEmpty

@ -7,28 +7,28 @@
import Foundation
/// A class extending the capabilities of StoredCollection but supposedly manages only one item
public class StoredSingleton<T: Storable>: StoredCollection<T> {
/// Sets the singleton to the collection without synchronizing it
public func setItemNoSync(_ instance: T) {
self.setSingletonNoSync(instance: instance)
}
/// updates the existing singleton
public func update() throws {
if let item = self.item() {
try self.addOrUpdate(instance: item)
}
}
/// Returns the singleton
public func item() -> T? {
return self.items.first
}
// MARK: - Protects from use
// public override func addOrUpdate(instance: T) throws {
// fatalError("method unavailable for StoredSingleton")
// }
public override func addOrUpdate(contentOfs sequence: any Sequence<T>) throws {
fatalError("method unavailable for StoredSingleton, use update")
}

Loading…
Cancel
Save