caiyue1993 / IceCream

Sync Realm Database with CloudKit
MIT License
1.95k stars 248 forks source link

Synced records mismatch when Large sync operation #242

Open elliotcz97 opened 3 years ago

elliotcz97 commented 3 years ago

Expected behavior

I want my objects to get synced correctly and stay correct

Actual behavior(optional)

When i sync a large amount of records (3k+) then some of them are not synced correctly.

I have an app where the User can schedule Events, these events have a list containing Services The Services are only a reference in each event. this is because of storage and other things.

The Service has a price property. When this property is changed, then all the events containing the Service gets updated by Realm, and therefore also by IceCream

When this update happens, then sometimes the price property remains unchanged, but the Event shows the right price. So some data got synced some not.

When i make that big update, i call syncEnginge.pushAll() I want to sync changes made on an iPad to my iPhone.

These are the models im using:

Events

class  Event: Object {

    @objc  dynamic  var  id = NSUUID().uuidString
    @objc  dynamic  var  isDeleted: Bool = false

    @objc  dynamic  var  eventName: String = "Minta Monika"
    @objc  dynamic  var  honnanIsmerem: String? = ""
    @objc  dynamic  var  eventLocation: String = "BP"
    @objc  dynamic  var  eventStartDate: Date = Date()
    @objc  dynamic  var  eventEndDate: Date = Date()

    var eventJelzes = RealmProperty<Int?>()

    @objc  dynamic  var  ismeteltEvent = false
    @objc  dynamic  var  ismetlesID: String? = nil
    var ismetlesGyakorisaga = RealmProperty<Int?>()
    @objc  dynamic  var  ismetlesTipus: String? = nil
    @objc  dynamic  var  meddigVanImetles: Date? = nil

    var eventService = List<ArlistaElem>()

    @objc  dynamic  var  eventPrice: Double = 0

    var usedKupon = LinkingObjects(fromType: Kupon.self, property: "usedInEventsList")

    override  class  func  primaryKey() -> String? {
        return "id"
    }
}

Services

class ArlistaElem: Object {

    @objc  dynamic  var id = NSUUID().uuidString
    @objc dynamic var isDeleted: Bool = false

    @objc dynamic var listaNev = "ListaNev"
    @objc dynamic var listaAr: Double = 500
    @objc dynamic var listaKategoria = "ListaKetegoria"
    @objc dynamic var listaKedvenc = false

    @objc dynamic var isArchived: Bool = false

    var parentCategory = LinkingObjects(fromType: ArlistaKategoria.self, property: "kezelesLista")

    override class func primaryKey() -> String? {
        return "id"
    }
}

Can someone help me? Because i could not get it to work after a week! I would really appreciate some good advice. Thank you!

LukeDurrant commented 3 years ago

I think possibly you're hitting CloudKit API limitations. There is a hard limit to the number of references with a CKReferenceActionDeleteSelf action that any one record can have. This limit is 750 references, and any attempt to exceed it results in an error from the server. Are you hitting https://developer.apple.com/documentation/cloudkit/ckreference

elliotcz97 commented 3 years ago

Maybe you are right! And how could i takle this problem if this is the issue?

LukeDurrant commented 3 years ago

I think its the way that Ice cream does a zone which doesn't give the greatest flexibility. Also iOS 15 allows the sharing of a zone which you couldn't do before. (and Ice cream doesn't support sharedDatabases) I'm trying to figure out a way to do this with being backwards compatible.

elliotcz97 commented 3 years ago

@LukeDurrant Thank you for your answer! I updated my Original Question with the code of the Models so that you have a better view of the whole. It is a many-to-many relationship i guess, but if im right then ice cream does support that.

One other question @caiyue1993 what does the U the V and the W mean/stand for in the SyncObject initializer? Maybe i used the wrong one.

aehlke commented 2 years ago

750 shouldnt be the limit since icecream sets reference action to .none instead of .deleteSelf