optimize reference checking

sync3
Laurent 5 months ago
parent 14252dfce0
commit c6804b3e81
  1. 7
      LeStorage/Codables/ApiCall.swift
  2. 3
      LeStorage/Codables/DataAccess.swift
  3. 3
      LeStorage/Codables/DataLog.swift
  4. 3
      LeStorage/Codables/FailedAPICall.swift
  5. 11
      LeStorage/Codables/GetSyncData.swift
  6. 3
      LeStorage/Codables/Log.swift
  7. 2
      LeStorage/Storable.swift
  8. 2
      LeStorage/Store.swift
  9. 23
      LeStorage/StoreCenter.swift
  10. 13
      LeStorage/StoredCollection.swift
  11. 4
      LeStorage/SyncedCollection.swift

@ -107,6 +107,9 @@ public class ApiCall<T: Storable>: ModelObject, Storable, SomeCall {
var storeId: String? { return self.urlParameters?[Services.storeIdURLParameter] } var storeId: String? { return self.urlParameters?[Services.storeIdURLParameter] }
public static func relationships() -> [Relationship] { return [] } public static func relationships() -> [Relationship] { return [] }
public static func parentRelationships() -> [Relationship] { return [] }
public static func childrenRelationships() -> [Relationship] { return [] }
} }
class OldApiCall<T: Storable>: ModelObject, Storable, SomeCall { class OldApiCall<T: Storable>: ModelObject, Storable, SomeCall {
@ -188,7 +191,9 @@ class OldApiCall<T: Storable>: ModelObject, Storable, SomeCall {
var dataContent: String? { return self.body } var dataContent: String? { return self.body }
static func relationships() -> [Relationship] { return [] } static func relationships() -> [Relationship] { return [] }
public static func parentRelationships() -> [Relationship] { return [] }
public static func childrenRelationships() -> [Relationship] { return [] }
func toNewApiCall() -> ApiCall<T>? { func toNewApiCall() -> ApiCall<T>? {
if let instance: T = try? self.body?.decode() { if let instance: T = try? self.body?.decode() {
let apiCall = ApiCall(method: self.method, data: instance, transactionId: self.transactionId) let apiCall = ApiCall(method: self.method, data: instance, transactionId: self.transactionId)

@ -12,6 +12,9 @@ class DataAccess: SyncedModelObject, SyncedStorable {
static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func resourceName() -> String { return "data-access" } static func resourceName() -> String { return "data-access" }
static func relationships() -> [Relationship] { return [] } static func relationships() -> [Relationship] { return [] }
public static func parentRelationships() -> [Relationship] { return [] }
public static func childrenRelationships() -> [Relationship] { return [] }
static var copyServerResponse: Bool = false static var copyServerResponse: Bool = false
static func storeParent() -> Bool { return false } static func storeParent() -> Bool { return false }

@ -12,6 +12,9 @@ class DataLog: ModelObject, Storable {
static func resourceName() -> String { return "data-logs" } static func resourceName() -> String { return "data-logs" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func relationships() -> [Relationship] { return [] } static func relationships() -> [Relationship] { return [] }
public static func parentRelationships() -> [Relationship] { return [] }
public static func childrenRelationships() -> [Relationship] { return [] }
static func storeParent() -> Bool { return false } static func storeParent() -> Bool { return false }
var id: String = Store.randomId() var id: String = Store.randomId()

@ -12,6 +12,9 @@ class FailedAPICall: SyncedModelObject, SyncedStorable {
static func resourceName() -> String { return "failed-api-calls" } static func resourceName() -> String { return "failed-api-calls" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func relationships() -> [Relationship] { return [] } static func relationships() -> [Relationship] { return [] }
public static func parentRelationships() -> [Relationship] { return [] }
public static func childrenRelationships() -> [Relationship] { return [] }
static var copyServerResponse: Bool = false static var copyServerResponse: Bool = false
static func storeParent() -> Bool { return false } static func storeParent() -> Bool { return false }

@ -12,13 +12,13 @@ class GetSyncData: SyncedModelObject, SyncedStorable, URLParameterConvertible {
static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static var copyServerResponse: Bool = false static var copyServerResponse: Bool = false
static func storeParent() -> Bool { return false } static func storeParent() -> Bool { return false }
var date: String = "" var date: String = ""
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case date case date
} }
override required init() { override required init() {
super.init() super.init()
} }
@ -49,6 +49,9 @@ class GetSyncData: SyncedModelObject, SyncedStorable, URLParameterConvertible {
let encodedDate = self.date.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" let encodedDate = self.date.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
return encodedDate.replacingOccurrences(of: "+", with: "%2B") return encodedDate.replacingOccurrences(of: "+", with: "%2B")
} }
static func relationships() -> [Relationship] { return [] } static func relationships() -> [Relationship] { return [] }
public static func parentRelationships() -> [Relationship] { return [] }
public static func childrenRelationships() -> [Relationship] { return [] }
} }

@ -12,6 +12,9 @@ class Log: SyncedModelObject, SyncedStorable {
static func resourceName() -> String { return "logs" } static func resourceName() -> String { return "logs" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func relationships() -> [Relationship] { return [] } static func relationships() -> [Relationship] { return [] }
public static func parentRelationships() -> [Relationship] { return [] }
public static func childrenRelationships() -> [Relationship] { return [] }
static var copyServerResponse: Bool = false static var copyServerResponse: Bool = false
static func storeParent() -> Bool { return false } static func storeParent() -> Bool { return false }

@ -34,6 +34,8 @@ public protocol Storable: Codable, Identifiable, NSObjectProtocol {
/// This method returns RelationShips objects of the type /// This method returns RelationShips objects of the type
static func relationships() -> [Relationship] static func relationships() -> [Relationship]
static func parentRelationships() -> [Relationship]
static func childrenRelationships() -> [Relationship]
static func storeParent() -> Bool static func storeParent() -> Bool

@ -288,7 +288,7 @@ final public class Store {
func isReferenced<T: Storable, S: Storable>(collectionType: S.Type, type: T.Type, id: String) -> Bool { func isReferenced<T: Storable, S: Storable>(collectionType: S.Type, type: T.Type, id: String) -> Bool {
if let collection = self._baseCollections[S.resourceName()] { if let collection = self._baseCollections[S.resourceName()] {
return collection.isReferenced(type: type, id: id) return collection.hasParentReferences(type: type, id: id)
} else { } else {
return false return false
} }

@ -813,6 +813,10 @@ public class StoreCenter {
self._deleteLogs.addOrUpdate(instance: dataLog) self._deleteLogs.addOrUpdate(instance: dataLog)
} }
/// Returns the appropriate store for a relationship
/// - Parameters:
/// - instance: some Storable instance
/// - relationship: the relationship
func relationshipStore<T: Storable>(instance: T, relationship: Relationship) -> Store? { func relationshipStore<T: Storable>(instance: T, relationship: Relationship) -> Store? {
switch relationship.storeLookup { switch relationship.storeLookup {
case .main: return Store.main case .main: return Store.main
@ -821,8 +825,13 @@ public class StoreCenter {
} }
} }
func hasDirectReference<T: Storable, S: Storable>(instance: T, relationshipType: S.Type, relationship: Relationship) -> Bool { /// Returns if an instance has at least one valid parent relationship by checking if the id of the parent exists
if let referenceId = instance[keyPath: relationship.keyPath] as? S.ID, let store = self.relationshipStore(instance: instance, relationship: relationship) { /// - Parameters:
/// - instance: some Storable instance
/// - relationship: the relationship
func hasParentReferences<T: Storable, S: Storable>(instance: T, relationshipType: S.Type, relationship: Relationship) -> Bool {
if let referenceId = instance[keyPath: relationship.keyPath] as? S.ID,
let store = self.relationshipStore(instance: instance, relationship: relationship) {
let instance: S? = store.findById(referenceId) let instance: S? = store.findById(referenceId)
return instance != nil return instance != nil
} }
@ -830,12 +839,14 @@ public class StoreCenter {
} }
func isReferenced<T: Storable>(instance: T) -> Bool { func isReferenced<T: Storable>(instance: T) -> Bool {
let relationships = T.relationships()
for relationship in relationships { for relationship in T.parentRelationships() {
if self.hasDirectReference(instance: instance, relationshipType: relationship.type, relationship: relationship) { if self.hasParentReferences(instance: instance, relationshipType: relationship.type, relationship: relationship) {
return true return true
} }
}
for relationship in T.childrenRelationships() {
if let store = self.relationshipStore(instance: instance, relationship: relationship) { if let store = self.relationshipStore(instance: instance, relationship: relationship) {
if store.isReferenced(collectionType: relationship.type, type: T.self, id: instance.stringId) { if store.isReferenced(collectionType: relationship.type, type: T.self, id: instance.stringId) {
return true return true

@ -17,7 +17,7 @@ public protocol SomeCollection<Item>: Identifiable {
var type: any Storable.Type { get } var type: any Storable.Type { get }
func reset() func reset()
func isReferenced<S: Storable>(type: S.Type, id: String) -> Bool func hasParentReferences<S: Storable>(type: S.Type, id: String) -> Bool
var items: [Item] { get } var items: [Item] { get }
@ -528,8 +528,8 @@ public class StoredCollection<T: Storable>: SomeCollection {
// MARK: - Reference count // MARK: - Reference count
/// Counts the references to an object - given its type and id - inside the collection /// Counts the references to an object - given its type and id - inside the collection
public func isReferenced<S: Storable>(type: S.Type, id: String) -> Bool { public func hasParentReferences<S: Storable>(type: S.Type, id: String) -> Bool {
let relationships = T.relationships().filter { $0.type == type } let relationships = T.parentRelationships().filter { $0.type == type }
guard relationships.count > 0 else { return false } guard relationships.count > 0 else { return false }
for item in self.items { for item in self.items {
@ -540,13 +540,6 @@ public class StoredCollection<T: Storable>: SomeCollection {
} }
} }
return false return false
// return self.items.reduce(0) { count, item in
// count
// + relationships.filter { relationship in
// (item[keyPath: relationship.keyPath] as? String) == id
// }.count
// }
} }
// MARK: - for Synced Collection // MARK: - for Synced Collection

@ -458,8 +458,8 @@ public class SyncedCollection<T : SyncedStorable>: SomeSyncedCollection, Collect
public var type: any Storable.Type { return T.self } public var type: any Storable.Type { return T.self }
public func isReferenced<S>(type: S.Type, id: String) -> Bool where S : Storable { public func hasParentReferences<S>(type: S.Type, id: String) -> Bool where S : Storable {
return self.collection.isReferenced(type: type, id: id) return self.collection.hasParentReferences(type: type, id: id)
} }
public func reset() { public func reset() {

Loading…
Cancel
Save