Missing mandatory realm fields in atlas

Hi there,

I’m trying to build an app using Realm Sync feature but I face an issue that i don’t understand.
In Realm schema, I define an class with some fields marked as required.
On the app side, an object is instantiated.
What i noticed :
if a mandatory int field is set to 0, a string field is set to “” or a boolean is set to false, at creation time, the matching field are not created in the atlas Document.

no big trouble until then, BUT , if you stop the Sync ( change in the schema or in sync config ), then it is not possible to turn it on again cleanly as object won’t get re synchronized.

Log shows message complaining about missing required field ( which is true as they’re missing in atlas documents) .

here is my class schema definition:

    {
      "title": "Log",
      "bsonType": "object",
      "properties": {
        "_id": {
          "bsonType": "objectId"
        },
        "__partition": {
          "bsonType": "string"
        },
        "type": {
          "bsonType": "int"
        },
        "result": {
          "bsonType": "bool"
        },
        "message": {
          "bsonType": "string"
        },
        "authorId": {
          "bsonType": "string"
        },
        "createdOn": {
          "bsonType": "date"
        }
      },
      "required": [
        "_id",
        "result",
        "type",
        "message",
        "authorId",
        "createdOn"
      ]
    }

an instance of Log object is created with “type” field set to 0 and message set to an empty string.
Here is what i get in the atlas collection

{"_id":{"$oid":“604b7c401fcf488cfeec9f51”},"__partition":“xxx”,“authorId”:“id”,“createdOn”:{"$date":“2021-03-12T14:35:44.105Z”},“result”:true}

A small precision: if these fields are set to a different value then set back to the wanted one (0, false or “” ), then the field remain present in the atlas document.

This look like a bug.

Am I missing something in my schema declaration or in Atlas configuration?

Thanks in advance.

Hi @bruno_levx welcome to the community!

Which SDK are you using?

Could you share the Object definitions from your app?

Thanks.

Hi Andrew,

I don’t think there is anything related to the SDK We’re using => swiftUI SDK 10.7.2.
This seems to be purely an issue between realm sync and Atlas Db on the MongodB servers.

here is the object definition:

public class Log: PartitionObject {
   
    @objc public dynamic var type:Int = 0
    @objc public dynamic var result:Int = 0
    @objc public dynamic var objectClass:String = ""
    @objc public dynamic var objectId:String = ""
    @objc public dynamic var identity:String?
    @objc public dynamic var message:String?
    @objc public dynamic var createdOn:Date = Date()
    
    public override class func primaryKey() -> String {
        return "_id"
    }
    
    public override var description: String{
        return "log"
    }
}

and the interfaces :

public protocol KItemStoring {
    var _id:ObjectId {get set}
    var __partition:String?  {get set}
}

public class PartitionObject:Object, ObjectKeyIdentifiable, KItemStoring {
    @objc public dynamic var _id:ObjectId = ObjectId.generate()
    @objc public dynamic var __partition:String?
}

@bruno_levx thanks for the extra details.

Can you confirm that the Object in the iOS has the correct data (even after sync?)

One way to easily check is using Realm Studio - as described here.

Hi andrew,

We already did that check when we noticed the issue. Yes, the value is correctly inserted in the object.
Just the atlas DB doesn’t reflect it.

regards,

Thanks - that narrows down who I can ask to look deeper into this. I’ll reach out to the translator team

@bruno_levx Could you please provide an example of how you’re creating one of these Objects where ""/false are being mapped to a missing attribute?

here is code sample in swift for another class

public class License: EmbeddedObject {

    @objc public dynamic var _id:ObjectId = ObjectId.generate()
    @objc public dynamic var __partition:String?
    @objc public dynamic var isEnabled:Bool = false
    @objc public dynamic var comment:String = ""
    @objc public dynamic var extensions:Int = 524287
    @objc public dynamic var maxRegistrationDisplay:Int = 0
    @objc public dynamic var maxDisplayController:Int = 0
    @objc public dynamic var maxCamera:Int = 0
    @objc public dynamic var validUntil:Date?

    public convenience required init(partition:String) {
        self.init()
        self.__partition = partition
    }
}

Instantiated like this:

License(partition: partition)

here is the document on atlas:

_id: 6051cc7091942e269dc03b47
__partition: "603a72fd6afac24e45e2be84"
extensions: 524287

As you can see, isEnabled, comment, maxRegistrationDisplay, MaxDisplayController, maxCamera, validUntil are missing in atlas

I we change the definition of maxCamera as followed :

@objc public dynamic var maxCamera:Int = 1

then the document look like:

_id: 60527aa8ee5e8115a733b3f4
__partition: "603a72fd6afac24e45e2be84"
extensions: 524287
maxCamera: 1

here is the realm schema on mongoDB realm interface:

{
    "title": "License",
    "bsonType": "object",
    "properties": {
      "_id": {
        "bsonType": "objectId"
      },
      "__partition": {
        "bsonType": "string"
      },
      "comment": {
        "bsonType": "string"
      },
      "validUntil": {
        "bsonType": "date"
      },
      "extensions": {
        "bsonType": "int"
      },
      "isEnabled": {
        "bsonType": "bool"
      },
      "maxCamera": {
        "bsonType": "int"
      },
      "maxDisplayController": {
        "bsonType": "int"
      },
      "maxRegistrationDisplay": {
        "bsonType": "int"
      }
    },
    "required": [
      "_id",
      "comment",
      "extensions",
      "isEnabled",
      "maxCamera",
      "maxDisplayController",
      "maxRegistrationDisplay"
    ]
  }

Hi @bruno_levx it appears that there’s an issue when you rely on the default values when creating Objects. Try updating your init to explicitly set the values of all of the attributes to work around that issue.

hi andrew,

That’s a bit annoying if you’re true. I guess we’re not the only ones who rely on properties default values. in that case there will be incomplete document in atlas db that will have to be manually corrected.

we’ll drive a test asap and keep you posted.

bruno.

Hi Andrew,

unfortunately we got the same results assigning values explicitely in init:

import Foundation
import RealmSwift

public class License: EmbeddedObject {
    
    @objc public dynamic var _id:ObjectId = ObjectId.generate()
    @objc public dynamic var __partition:String?
    @objc public dynamic var isEnabled:Bool = true
    @objc public dynamic var comment:String = "Comment"
    @objc public dynamic var extensions:Int = 524287
    @objc public dynamic var maxRegistrationDisplay:Int = 0
    @objc public dynamic var maxDisplayController:Int = 0
    @objc public dynamic var maxCamera:Int = 0
    @objc public dynamic var validUntil:Date?

    public convenience required init(partition:String, validUntil:Date? = nil) {
        self.init()
        self.__partition = partition
        self.validUntil = validUntil
        self.maxRegistrationDisplay = 0
        self.maxDisplayController = 0
        self.maxCamera = 0
    }
}

result in atlas :

_id: 60531edafc2b58fd7cd33bc1
__partition: "603a72fd6afac24e45e2be84"
isEnabled: true
comment: "Comment"
extensions: 524287

best regards,
Bruno

Hi there,

Already 7 days since My last post, any updates or test you want we realize ?

Bruno,

@Ian_Ward am I missing something?

@bruno_levx Hi can you please provide a reproduction case and file it here please -

This the same behavior with the dotnet SDK as well. When you leave the defaults like int = 0 or bool = false, the field never propagates to Atlas.

Then in my _realm_sync database I start to accumulate documents in the collection unsynced_documents

@bruno_levx can you connect directly to your Atlas instance and check your unsynced_documents? The two way sync seems to break as well and I think you will have documents in here.

One more note of interest, if you edit the document directly via the web interface, the document will simply disappear from the client. This seems to be because of the document not matching the schema due to missing fields.

Hi Michael,

You probably have unsynced documents because, as you mentioned, you’re modifying them from atlas. As we didn’t do such thing we didn’t face this issue but the root cause is the same what we pinpoint : due to missing fields, atlas documents can never be synced to a realm from atlas.
We noticed this when turning off the Sync : we are then unable to turn it on again.

I hope you’re not in production phase! otherwise I warmly advise you to not turn off the sync unless you manually add all the missing fields in atlas documents.
This means no partition key or permissions changes (sync off/on) nor destructive schema changes (which will leads to the same result =>sync off then on).

@Ian_Ward : I still didn’t open the github issue. We were quite overwhelmed past few days and we want to try downgrade the realm cocoa Pod to check if the behavior was already present. (we don’t remember noticing such issue before we update to the last version)

regards
Bruno

Hi,

I’ve made a small C# app to test and i confirm that the behavior is almost the same except than in my test empty tring are correctly synced. Int value zet to 0 are still Missing.

i’ll open a file on github right now and paste the link here for those, like Martin, who are intersted in that issue.

Regards,
Bruno

Here is to the link to the GitHub file :
Missing mandatory realm fields in atlas when set to “base” value. · Issue #7192 · realm/realm-cocoa (github.com)

Regards,
Bruno

@Andrew_Morgan
Just a quick additional question regarding this issue:

We tried to use the workaround mentioned above ( removing .modified parameter). This works great but bring another issue.
if the inserted object refer to an already existing one, then an duplicate objectId exception is raised.

Is there any way to prevent realm.add() function to try to also add objects declared in a link.

(Maybe we missed something obvious once again…)

regards,
Bruno

Hey All - just as an update we’ve fixed this behavior on the server and should have this out in the next release, likely end of next week. Thank you for the repro cases

-Ian

1 Like