|
|
|
|
@ -41,7 +41,7 @@ public class BaseCollection<T: Storable>: SomeCollection, CollectionHolder { |
|
|
|
|
fileprivate var _indexes: [T.ID: T]? = nil |
|
|
|
|
|
|
|
|
|
/// A PendingOperationManager instance that manages operations while the collection is not loaded |
|
|
|
|
fileprivate var _pendingOperationManager: PendingOperationManager<T>? = nil |
|
|
|
|
fileprivate(set) var pendingOperationManager: PendingOperationManager<T>? = nil |
|
|
|
|
|
|
|
|
|
/// Indicates whether the collection has changed, thus requiring a write operation |
|
|
|
|
fileprivate var _hasChanged: Bool = false { |
|
|
|
|
@ -145,24 +145,6 @@ public class BaseCollection<T: Storable>: SomeCollection, CollectionHolder { |
|
|
|
|
name: NSNotification.Name.CollectionDidLoad, object: self) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _mergePendingOperations() { |
|
|
|
|
|
|
|
|
|
guard let manager = self._pendingOperationManager, manager.items.isNotEmpty else { return } |
|
|
|
|
|
|
|
|
|
Logger.log(">>> Merge pending: \(manager.items.count)") |
|
|
|
|
let methodGroups = manager.items.group { $0.method } |
|
|
|
|
for (method, group) in methodGroups { |
|
|
|
|
let dataArray = group.map { $0.data } |
|
|
|
|
switch method { |
|
|
|
|
case .addOrUpdate: |
|
|
|
|
self.addOrUpdate(contentOfs: dataArray) |
|
|
|
|
case .delete: |
|
|
|
|
self.delete(contentOfs: dataArray) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
self._pendingOperationManager = nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Sets a collection of items and indexes them |
|
|
|
|
func setItems(_ items: [T]) { |
|
|
|
|
for item in items { |
|
|
|
|
@ -272,10 +254,10 @@ public class BaseCollection<T: Storable>: SomeCollection, CollectionHolder { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Adds an instance to the collection |
|
|
|
|
@discardableResult func addItem(instance: T, checkLoaded: Bool = true) -> Bool { |
|
|
|
|
@discardableResult func addItem(instance: T, checkLoaded: Bool = true, shouldBeSynchronized: Bool = false) -> Bool { |
|
|
|
|
|
|
|
|
|
if checkLoaded && !self.hasLoaded { |
|
|
|
|
self._addPendingOperation(method: .addOrUpdate, instance: instance) |
|
|
|
|
self._addPendingOperation(method: .addOrUpdate, instance: instance, shouldBeSynchronized: shouldBeSynchronized) |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -288,10 +270,10 @@ public class BaseCollection<T: Storable>: SomeCollection, CollectionHolder { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Updates an instance to the collection by index |
|
|
|
|
@discardableResult func updateItem(_ instance: T, index: Int, checkLoaded: Bool = true) -> Bool { |
|
|
|
|
@discardableResult func updateItem(_ instance: T, index: Int, checkLoaded: Bool = true, shouldBeSynchronized: Bool = false) -> Bool { |
|
|
|
|
|
|
|
|
|
if checkLoaded && !self.hasLoaded { |
|
|
|
|
self._addPendingOperation(method: .addOrUpdate, instance: instance) |
|
|
|
|
self._addPendingOperation(method: .addOrUpdate, instance: instance, shouldBeSynchronized: shouldBeSynchronized) |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -306,26 +288,19 @@ public class BaseCollection<T: Storable>: SomeCollection, CollectionHolder { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Deletes an instance from the collection |
|
|
|
|
@discardableResult func deleteItem(_ instance: T) -> Bool { |
|
|
|
|
@discardableResult func deleteItem(_ instance: T, shouldBeSynchronized: Bool = false) -> Bool { |
|
|
|
|
|
|
|
|
|
if !self.hasLoaded { |
|
|
|
|
self._addPendingOperation(method: .addOrUpdate, instance: instance) |
|
|
|
|
self._addPendingOperation(method: .addOrUpdate, instance: instance, shouldBeSynchronized: shouldBeSynchronized) |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
instance.deleteDependencies() |
|
|
|
|
instance.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) |
|
|
|
|
self.items.removeAll { $0.id == instance.id } |
|
|
|
|
self._indexes?.removeValue(forKey: instance.id) |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _addPendingOperation(method: StorageMethod, instance: T) { |
|
|
|
|
if self._pendingOperationManager == nil { |
|
|
|
|
self._pendingOperationManager = PendingOperationManager<T>(store: self.store, inMemory: self.inMemory) |
|
|
|
|
} |
|
|
|
|
self._pendingOperationManager?.addPendingOperation(method: method, instance: instance) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// If the collection has more instance that its limit, remove the surplus |
|
|
|
|
fileprivate func _applyLimitIfPresent() { |
|
|
|
|
if let limit { |
|
|
|
|
@ -361,6 +336,51 @@ public class BaseCollection<T: Storable>: SomeCollection, CollectionHolder { |
|
|
|
|
self.delete(contentOfs: self.items) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// MARK: - Pending operations |
|
|
|
|
|
|
|
|
|
fileprivate func _addPendingOperation(method: StorageMethod, instance: T, shouldBeSynchronized: Bool) { |
|
|
|
|
if self.pendingOperationManager == nil { |
|
|
|
|
self.pendingOperationManager = PendingOperationManager<T>(store: self.store, inMemory: self.inMemory) |
|
|
|
|
} |
|
|
|
|
self.addPendingOperation(method: method, instance: instance, shouldBeSynchronized: false) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func addPendingOperation(method: StorageMethod, instance: T, shouldBeSynchronized: Bool) { |
|
|
|
|
self.pendingOperationManager?.addPendingOperation(method: method, instance: instance, shouldBeSynchronized: shouldBeSynchronized) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _mergePendingOperations() { |
|
|
|
|
|
|
|
|
|
guard let manager = self.pendingOperationManager, manager.items.isNotEmpty else { return } |
|
|
|
|
|
|
|
|
|
Logger.log(">>> Merge pending: \(manager.items.count)") |
|
|
|
|
for item in manager.items { |
|
|
|
|
let data = item.data |
|
|
|
|
switch (item.method, item.shouldBeSynchronized) { |
|
|
|
|
case (.addOrUpdate, true): |
|
|
|
|
self.addOrUpdate(instance: data) |
|
|
|
|
case (.addOrUpdate, false): |
|
|
|
|
self.addOrUpdateItem(instance: data) |
|
|
|
|
case (.delete, true): |
|
|
|
|
self.delete(instance: data) |
|
|
|
|
case (.delete, false): |
|
|
|
|
self.deleteItem(data) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// let methodGroups = manager.items.group { $0.method } |
|
|
|
|
// for (method, group) in methodGroups { |
|
|
|
|
// let dataArray = group.map { $0.data } |
|
|
|
|
// switch method { |
|
|
|
|
// case .addOrUpdate: |
|
|
|
|
// self.addOrUpdate(contentOfs: dataArray) |
|
|
|
|
// case .delete: |
|
|
|
|
// self.delete(contentOfs: dataArray) |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
self.pendingOperationManager = nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// MARK: - File access |
|
|
|
|
|
|
|
|
|
/// Schedules a write operation |
|
|
|
|
|