Do I understand this correctly? partitionKey == partitionValue

Help me get this straight:

[1.]
When you open a synced realm DB with a specific partitionValue:
eg.

let config = app.currentUser!.configuration(partitionValue: "user=\(user.id)")
let userRealm = try! Realm(configuration: config)

Every object transaction to this db (eg. a write), must also have a matching _partitionKey value:
eg.

class RLMCar: Object {
    @objc dynamic var _partitionKey: String = ""

    convenience init(partitionKey: String) {
        self.init()
        self._partitionKey = partitionKey
    }
...

let car = RLMCar(partitionKey: "user=\(user.id)")
userRealm?.createOrUpdateAll(with: [car])

Otherwise… if an objects _partitionKey is different from the opened realm’s partitionValue:
eg.

let car = RLMCar(partitionKey: "user=\(appSession.userProfile.email)")
userRealm?.createOrUpdateAll(with: [car])

The object will still save correctly to the local realm db on device, but fail to sync, resulting in:

Received: ERROR(error_code=212, message_size=22, try_again=0)

With the server log stating BadChange:

[2.]
If you sync from multiple realms into the same MongoDB, the collection view UI on the server will show multiple objects (“Documents”?) with different _partitionKey's. Which would indicate they came from separate realm’s.


I should probably add error checking in my function wrapper to verify the Object’s partitionKey == partitionValue before writing it.

[3.]
As a side note: why does Realm insert empty tables of every Object class into the database file, even though there aren’t any actions performed on creating and actually writing those objects?

[1.]
Regarding the first question: typically, in the documentation, we refer to the property name as “partition key” and the property value as “partition value”. In your example, your partition key is called _partitionKey and the partition values are the values this property can take - such as "123", "abc", and so on. If you do have the _partitionKey property explicitly defined in your models, then you should set its value to the same value as the value you opened the synchronized Realm with.

To avoid confusion though, it is perfectly legal to omit the partition key property from your Swift models. That way, the SDK will not set it to anything and the server will automatically populate it to the expected value.

[2.]
I’m not sure that I understand your second question or is it merely an observation? It is expected that a single MongoDB collection will contain documents from multiple partitions/Realms and indeed the value of the _partition property is what determines which Realm a document is associated with.

[3.]
Realm is inherently a schema-based database. The schema is persisted upon opening the Realm file, regardless of whether there are objects created in a particular table or not. Is there a reason why you’re concerned with this behavior?

Hi Nikola,
re:
[1.]

To avoid confusion though, it is perfectly legal to omit the partition key property from your Swift models. That way, the SDK will not set it to anything and the server will automatically populate it to the expected value.

If I remove the _partitionKey property from my Swift models, I get the dreaded error_code=212, and sync is broken. As it doesn’t match the cloud model schema.

If I try to remove it from the cloud model schema, I get:

So that doesn’t make sense to me in its setup.

[2.]
Correct, this is an observation. Thank you for confirming.

[3.]
Just curious about this operation. Thanks.

Hey Sebastian,

_partitionKey should be in your JSON Schema (the cloud models) - there’s no way around this.

It’s very surprising that you’re getting 212 when you remove it from your swift models though. Have you tried doing it recently - it was not possible some months ago, but I’m fairly certain it should be legal today. Your Swift models are absolutely free to define a subset of the properties/classes that exist on the server. The partition key and the _id were the only exceptions, but the team resolved the issues with the partition keys and you no longer have to include them in your client models.

If you do get the error with the latest version of the Swift SDK, would you mind opening a Github issue with some details and ideally a repro case so the team can investigate.

Hi Nikola,

It works! I just had to delete my app.

class RLMCar: Object {

    @objc dynamic var _id: String = newUUID
//    @objc dynamic var _partitionKey: String = ""

    @objc dynamic var serverLastUpdated: String? = nil
    @objc dynamic var clientLastUpdated: String? = nil
...

The server side document synced the object:

And my local realm file shows the _partitionKey property in the table. But curiously, it’s empty. :thinking:

Is this expected behaviour?
Realm sync won’t update my local realm object with the servers _partitionKey?

As another side thought: when opening a Realm(…) DB, is the main difference in triggering a synced realm vs. a non-synced realm, by providing a partitionValue in its parameters?

The partition value should get synced back to your client, though that may take a few seconds as it needs to go to the server and back (i.e. it’s not populated on the device). If you don’t see it get synced back, that will be suspicious and I’ll open a bug report with the cloud team to investigate.

As for the difference between synced and local Realm - yes, providing a user and a partition key is the main difference. That information will tell Realm that your intent is to synchronize the data with a MongoDB Realm app and initialize the sync mechanism.

If you don’t see it get synced back, that will be suspicious and I’ll open a bug report with the cloud team to investigate.

Perfect! Here’s my video proof of the issue.

One scenario I did test as well is modifying a synced object on the server DB side. Upon the update and sync down to the client app, I noticed that the partitionValue for that single object did fill in.

This may be nothing but in the top part of the question the objects had a _partitionKey property and in the latter posts the property was _partition - and then it’s set back to _partitionKey in a screen shot.

What is that set to in the console->Sync settings?

@Jay I just changed the string and re-started/reset everything. Wondered if by chance the _partition string mattered to some internal code. But it doesn’t. ¯\(ツ)

Are you still having the same issue where the _partition (or _partitionKey) is not sync’ing back to the client?

Let me preface this be saying we’ve been using this set up for months and it’s always populated and worked correctly. Initially we were manually populating that but with the update that auto-populated, it’s never failed for us.

Did you verify the client has a Realm object with a property they matches what’s defined in the server Sync settings? e.g.

class TaskClass: Object {
    @objc dynamic var _id: ObjectId = ObjectId.generate()
    //@objc dynamic var _partitionKey = ""  this will auto populate so not needed

When the TaskClass object is instantiated and sync’d the _partitionKey value will be automatically populated with whatever Realm we connected to.

Then in the Console->Sync setting the partition key name has to match that property name (not the value)

Just like you, I was manually populating the _partition key value in my code on the app side.

Then, as @nirinchev stated above:

… it is perfectly legal to omit the partition key property from your Swift models.

Which I then did. The Realm Sync SDK adds the _partition column to my table automatically. But as seen in my video above, it does not auto-populate the key with any value after an up-sync.

But if you then modify that synced object on the server-side, when it then syncs back down, it will have the populated _partition key value.

To add more fuel to this process, I then tested re-enabling my _partition property in my object:

@objc dynamic var _partition: String = Partition.user

It crashed sync. hahaha… I guess there is some cache that although my Swift model now matches the .realm file tables exactly, the SDK fails to adapt and still expects my Swift model to omit the _partition property. :confused:

Ok. I made an error in the code in my above post. This was supposed to be commented out showing that even if the property does not exist in code, it’s still populated on the server.

//@objc dynamic var _partitionKey = "" this will auto populate so not needed

Now the interesting part; we are able to duplicate this (different) behavior.

@nirinchev

It was working and populating the partition key property in the realm file with a prior Realm version but with 10.5.1, it definitely does not populate the partition key locally.

Here’s the console and then the local realm file - it’s the same object but there is no local partition key

Yep, this sounds like a legitimate bug. It shouldn’t materially affect using the SDK, but we should fix it nonetheless.

Just a tad bit more info. If the local files are totally deleted and the app is run. It successfully sync’s and actually creates the partition key property in the file but does not populate it.

@nirinchev

I am happy to open a bug report, just not sure where to do it. Git? And is this a Realm-Cocoa SDK issue or does it fall under some other repository? Or should we chat them via the console?

The reporting path is a bit unclear so any direction would be appreciated.

From the looks of it, doesn’t seem like it’s Cocoa specific. If it’s something that’s negatively impacting your app/development process, then file a support ticket and the team will route it to the Cloud team (and ensure that SLAs are met and you’re continuously updated on the progress). Otherwise, I’ll file a ticket internally and make a note for whoever handles it to report back on this thread. But it’ll be lower priority than if it’s impacting a live app/app in active development.

@nirinchev

Well, they want me to pay to file a support ticket for a bug so I would please ask if you could file a ticket internally.

It’s not mission critical for us as we always include the _partitionKey property in our objects but it maybe for @Sebastian_Dwornik or others.

Not mission critical here too. (for now)
Just an observation as I tinker with learning this SDK. But it might be useful at some point.

Might the fix also resolve the sync error when I add back the _partition key property to my Swift model after initializing a realm without it?

What is the error you’re getting after adding the _partition property?

hmm… let’s leave that alone for now. Seems me trying to reproduce it isn’t working at the moment.

Cool - if you encounter it again - feel free to file a ticket for the Cocoa team.