cleanup and documentation

sync
Laurent 1 year ago
parent a978bbcbfa
commit 7a9f560ccf
  1. 9
      LeStorage/ApiCallCollection.swift
  2. 1
      LeStorage/ModelObject.swift
  3. 3
      LeStorage/Services.swift
  4. 5
      LeStorage/Store.swift
  5. 29
      LeStorage/StoredCollection.swift

@ -34,7 +34,8 @@ actor ApiCallCollection<T: Storable>: SomeCallCollection {
/// Indicates if the collection is currently retrying ApiCalls /// Indicates if the collection is currently retrying ApiCalls
fileprivate var _isRetryingCalls: Bool = false fileprivate var _isRetryingCalls: Bool = false
fileprivate var _executionTask: Task<Void, any Error>? = nil /// The task of waiting and executing ApiCalls
fileprivate var _reschedulingTask: Task<Void, any Error>? = nil
/// Indicates whether the collection content has changed /// Indicates whether the collection content has changed
/// Initiates a write when true /// Initiates a write when true
@ -122,7 +123,7 @@ actor ApiCallCollection<T: Storable>: SomeCallCollection {
/// Removes all objects in memory and deletes the JSON file /// Removes all objects in memory and deletes the JSON file
func reset() { func reset() {
self._executionTask?.cancel() self._reschedulingTask?.cancel()
self.items.removeAll() self.items.removeAll()
do { do {
@ -145,11 +146,11 @@ actor ApiCallCollection<T: Storable>: SomeCallCollection {
self._isRetryingCalls = true self._isRetryingCalls = true
self._attemptLoops += 1 self._attemptLoops += 1
self._executionTask = Task { self._reschedulingTask = Task {
let delay = pow(2, self._attemptLoops) let delay = pow(2, self._attemptLoops)
let seconds = NSDecimalNumber(decimal: delay).intValue let seconds = NSDecimalNumber(decimal: delay).intValue
Logger.log("wait for \(seconds) sec") Logger.log("\(T.resourceName()): wait for \(seconds) sec")
try await Task.sleep(until: .now + .seconds(seconds)) try await Task.sleep(until: .now + .seconds(seconds))
let apiCallsCopy = self.items let apiCallsCopy = self.items

@ -8,6 +8,7 @@
import Foundation import Foundation
/// A class used as the root class for Storable objects /// A class used as the root class for Storable objects
/// Provides default implementations of the Storable protocol
open class ModelObject { open class ModelObject {
public var store: Store? = nil public var store: Store? = nil

@ -240,6 +240,7 @@ public class Services {
/// Executes an ApiCall /// Executes an ApiCall
func runApiCall<T: Storable>(_ apiCall: ApiCall<T>) async throws -> T { func runApiCall<T: Storable>(_ apiCall: ApiCall<T>) async throws -> T {
let request = try self._request(from: apiCall) let request = try self._request(from: apiCall)
print("HTTP \(request.httpMethod ?? "") : id = \(apiCall.dataId)")
return try await self._runRequest(request, apiCallId: apiCall.id) return try await self._runRequest(request, apiCallId: apiCall.id)
} }
@ -298,9 +299,7 @@ public class Services {
/// - password: the account's password /// - password: the account's password
public func requestToken(username: String, password: String) async throws -> String { public func requestToken(username: String, password: String) async throws -> String {
var postRequest = try self._baseRequest(conf: .requestToken) var postRequest = try self._baseRequest(conf: .requestToken)
let deviceId = StoreCenter.main.deviceId() let deviceId = StoreCenter.main.deviceId()
Logger.log("deviceId = \(deviceId)")
let credentials = Credentials(username: username, password: password, deviceId: deviceId) let credentials = Credentials(username: username, password: password, deviceId: deviceId)
postRequest.httpBody = try jsonEncoder.encode(credentials) postRequest.httpBody = try jsonEncoder.encode(credentials)
let response: AuthResponse = try await self._runRequest(postRequest) let response: AuthResponse = try await self._runRequest(postRequest)

@ -8,11 +8,6 @@
import Foundation import Foundation
import UIKit import UIKit
//public enum ResetOption {
// case all
// case synchronizedOnly
//}
public enum StoreError: Error { public enum StoreError: Error {
case missingService case missingService
case missingUserId case missingUserId

@ -158,18 +158,10 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
} else { } else {
self._setAsLoaded() self._setAsLoaded()
} }
// else if self.synchronized {
// Task {
// do {
// try await self.loadDataFromServerIfAllowed()
// } catch {
// Logger.error(error)
// }
// }
// }
} }
/// Sets the collection as loaded
/// Send a CollectionDidLoad event
fileprivate func _setAsLoaded() { fileprivate func _setAsLoaded() {
self.hasLoaded = true self.hasLoaded = true
DispatchQueue.main.async { DispatchQueue.main.async {
@ -177,6 +169,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
} }
} }
/// Sets a collection of items and indexes them
fileprivate func _setItems(_ items: [T]) { fileprivate func _setItems(_ items: [T]) {
self.items = items self.items = items
self._updateIndexIfNecessary() self._updateIndexIfNecessary()
@ -205,6 +198,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
self._setAsLoaded() self._setAsLoaded()
} }
/// Loads the collection using the server data only if the collection file doesn't exists
func loadCollectionsFromServerIfNoFile() async throws { func loadCollectionsFromServerIfNoFile() async throws {
let fileURL: URL = try self._store.fileURL(type: T.self) let fileURL: URL = try self._store.fileURL(type: T.self)
if !FileManager.default.fileExists(atPath: fileURL.path()) { if !FileManager.default.fileExists(atPath: fileURL.path()) {
@ -288,6 +282,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
try self._addOrUpdate(contentOfs: sequence) try self._addOrUpdate(contentOfs: sequence)
} }
/// Adds or update a sequence of elements without synchronizing it
func addOrUpdateNoSync(contentOfs sequence: any Sequence<T>) throws { func addOrUpdateNoSync(contentOfs sequence: any Sequence<T>) throws {
try self._addOrUpdate(contentOfs: sequence, shouldSync: false) try self._addOrUpdate(contentOfs: sequence, shouldSync: false)
} }
@ -360,12 +355,14 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
// MARK: - Migrations // MARK: - Migrations
/// Makes POST ApiCall for all items in the collection
public func insertAllIntoCurrentService() { public func insertAllIntoCurrentService() {
for item in self.items { for item in self.items {
self._sendInsertionIfNecessary(item) self._sendInsertionIfNecessary(item)
} }
} }
/// Makes POST ApiCall for the provided item
public func insertIntoCurrentService(item: T) { public func insertIntoCurrentService(item: T) {
self._sendInsertionIfNecessary(item) self._sendInsertionIfNecessary(item)
} }
@ -410,20 +407,10 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
self.items.removeAll() self.items.removeAll()
} }
/// Removes the items of the collection, deletes the corresponding file, and also reset the related API calls collection /// Removes the items of the collection and deletes the corresponding file
public func reset() { public func reset() {
self.items.removeAll() self.items.removeAll()
self._store.removeFile(type: T.self) self._store.removeFile(type: T.self)
// do {
// let url: URL = try T.urlForJSONFile()
// if FileManager.default.fileExists(atPath: url.path()) {
// try FileManager.default.removeItem(at: url)
// }
// } catch {
// Logger.error(error)
// }
// self.resetApiCalls()
} }
// MARK: - Reschedule calls // MARK: - Reschedule calls

Loading…
Cancel
Save