Search code examples
realmmongodb-atlas

RealmSwift, how to handle breaking changes with Atlas Sync App Mongodb


I am currently working on an iOS app that uses RealmSwift that works with Atlas App Sync. When working on this in xCode any changes that I make to the model object classes results in breaking changes that results in sync errors. I understand that breaking changes that are not matching the JSON schema from the Atlas App will fail to sync. What I don't understand is how to handle those changes effectively.

For example, I have the following realmswift object persisted to my device and the schema on Atlas App that has no issues syncing.

/// On user/clients device

class Condition: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId?
    @Persisted var __v: Int?
    @Persisted var condition_string: String?
    
    
}

/// Schema on Atlas App
{
  "title": "Condition",
  "properties": {
    "__v": {
      "bsonType": "int"
    },
    "_id": {
      "bsonType": "objectId"
    },
    "condition_string": {
      "bsonType": "string"
    }
  }
}

If I were to change the class name from Condition to Conditions like such, an error syncing would occur.

/// On user/client device

class Conditions: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId?
    @Persisted var __v: Int?
    @Persisted var condition_string: String?
    
    
}

/// Schema on Atlas App
{
  "title": "Conditions",
  "properties": {
    "__v": {
      "bsonType": "int"
    },
    "_id": {
      "bsonType": "objectId"
    },
    "condition_string": {
      "bsonType": "string"
    }
  }
}

This results in an error when connecting to the Atlas App! Within the stored realm on the users/clients device, the realm object does not get updated to Conditions when I rebuild the app in xCode, it still shows the the old class Condition.

The only way I can get the sync to perform, is to completely delete the realm file and reinitialize the realm, and rebuild the project. At this point the sync function performs normally.

My question is why does the realm object not update to the new class name, when I rebuild it in xCode?

I believe this falls under migration changes, and currently my app is not handling them correctly. Any advice or help pointing to a solution would be appreciated.


Solution

  • Wow - super awesome question!

    What you've come across is a pain point in working with a synced Realm. I prefer code based answers but in this case, some explanation is probably best

    Local Realms have a super cool migration ability that will update and migrate objects as they change during development or when features are added. Additive changes (adding a property for example) only requires an update of the migration version. Desctructive changes (like removing a property) requires an update to the version and then additional code in the migration block to handle that change. It's a straight forward process and really pretty nifty!

    On the other hand, Synced Realms have no migrations. But there are ways to handling it.

    Changing a synced Realm falls into two types of changes: There are non-breaking and breaking changes, and in the case of non-breaking changes, it's super easy!

    Examples of non-breaking changes are things like adding an object, adding a property to an existing object. Those just happen magically - add a new object and Realm pics up and syncs (when using Development Mode). Done.

    Breaking changes (e.g. it breaks the sync) are things like removing an object or changing a property name. The pattern for handling these kinds of changes varies quite a bit. See the link above as it covers all the cases.

    In the early stages of development you'll be changing your objects frequently. I suggest taking the time to craft some code to delete all of your local files and then either logging into the Realm console and deleting the data manually or crafting a server side function that can be called from the app. Remembering that you'll need to terminate sync and restart sync each time.

    After that, and as your app ages, use the strategys in the guide on a per case basis, depending on the change type.