Uploaded image for project: 'Realm Core'
  1. Realm Core
  2. RCORE-1980

Non-symmetric results with conflicting default null value

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: None
    • Component/s: Sync
    • None

      Hi, I'm running into an odd issue with the StateApplierTool and applying conflicting isDefault writes. It looks like there may be some weirdness around the handling for null payloads/OT

      The repro inputs are attached here and detailed below

      Changeset #1
      Upload Message: [
          {
              "timestamp": 200,
              "instructions": [
                {
                   "summary": "CreateObject { table: \"ww\", id: UUID(3e3b5f26-a6b8-c14c-e4d7-4abe8e34ad8d) }",
                   "raw": "PwACd3cCAAs+O18mprjBTOTXSr6ONK2N"
                },
                {
                   "summary": "Update { (table=\"ww\", ID=UUID(3e3b5f26-a6b8-c14c-e4d7-4abe8e34ad8d), fullPath=\"qu\"), payload: -6.355252517323399e+307, isDefault: true, priorSize: 0 }",
                   "raw": "PwACd3c/AQJxdQQACz47XyamuMFM5NdKvo40rY0BAAeqDn59HaDW/wE="
                },
                {
                   "summary": "Update { (table=\"ww\", ID=UUID(3e3b5f26-a6b8-c14c-e4d7-4abe8e34ad8d), fullPath=\"ur\"), payload: 6.192209238937289e+307, isDefault: true, priorSize: 0 }",
                   "raw": "PwACd3c/AQJ1cgQACz47XyamuMFM5NdKvo40rY0BAAcmfHTmhAvWfwE="
                }
             ]
          }
      ],
      
      IDENT
      
      Changeset #2
      Download Message:[
          {  
             "timestamp": 100,
             "instructions": [
                {
                   "summary": "CreateObject { table: \"ww\", id: UUID(3e3b5f26-a6b8-c14c-e4d7-4abe8e34ad8d) }",
                   "raw": "PwACd3cCAAs+O18mprjBTOTXSr6ONK2N"
                },
                {
                   "summary": "Update { (table=\"ww\", ID=UUID(3e3b5f26-a6b8-c14c-e4d7-4abe8e34ad8d), fullPath=\"qu\"), payload: null, isDefault: true, priorSize: 0 }",
                   "raw": "PwACd3c/AQJxdQQACz47XyamuMFM5NdKvo40rY0BAAAB"
                },
                {
                   "summary": "Update { (table=\"ww\", ID=UUID(3e3b5f26-a6b8-c14c-e4d7-4abe8e34ad8d), fullPath=\"ur\"), payload: -1.338641371363204e+307, isDefault: true, priorSize: 0 }",
                   "raw": "PwACd3c/AQJ1cgQACz47XyamuMFM5NdKvo40rY0BAAfGE0VKGRCz/wE="
                }
             ]
          }
      ] 

      This series of events correctly produces the following realm: 

       

      {
          "_id": 3e3b5f26-a6b8-c14c-e4d7-4abe8e34ad8d,
          "qu": -6.355252517323399e+307,
          "ur": 6.192209238937289e+307,
      }

       

       

      If we instead flip the upload and download messages (Upload Changeset #2 and Download Changeset #1) we get the following realm where the field "qu" gets set to null but "ur" is still set to the correct value from CS1

      {
          "_id": 3e3b5f26-a6b8-c14c-e4d7-4abe8e34ad8d,
          "qu": null,
          "ur": 6.192209238937289e+307,
      }

      Verbose logs from state applier in the case that ends up with the incorrect result

      found upload changeset: 1 1 100 1 39
      Decoded changeset: [changeset with 3 instructions]
      found upload changeset: 2 2 100 1 88
      Decoded changeset: [changeset with 3 instructions]
      group.get_or_add_table_with_primary_key(group, "class_ww", type_UUID, "_id", true, TopLevel);
      integrated local changesets as version 6
      sync::create_object_with_primary_key(group, get_table("class_ww"), 3e3b5f26-a6b8-c14c-e4d7-4abe8e34ad8d);
      integrated local changesets as version 7
      decoding download message. {download: {server: 2, client: 0} upload: {server: 0, client: 0}, latest: 0}
      found download changeset: serverVersion: 1, clientVersion: 0, origin: 2 [changeset with 3 instructions]
      found download changeset: serverVersion: 2, clientVersion: 0, origin: 2 [changeset with 3 instructions]
      Scanning incoming changeset [1/2] (3 instructions)
      Scanning incoming changeset [2/2] (3 instructions)
      Scanning local changeset [1/4] (3 instructions)
      Scanning local changeset [2/4] (3 instructions)
      Scanning local changeset [3/4] (1 instructions)
      Scanning local changeset [4/4] (4 instructions)
      Indexing incoming changeset [1/2] (3 instructions)
      Indexing incoming changeset [2/2] (3 instructions)
      Finished changeset indexing (incoming: 2 changeset(s) / 6 instructions, local: 4 changeset(s) / 11 instructions, conflict group(s): 2)
      Transforming local changeset [1/4] through 2 incoming changeset(s) with 2 conflict group(s)
      Transforming local changeset [2/4] through 2 incoming changeset(s) with 2 conflict group(s)
      Transforming local changeset [3/4] through 2 incoming changeset(s) with 2 conflict group(s)
      Transforming local changeset [4/4] through 2 incoming changeset(s) with 2 conflict group(s)
      Finished transforming 4 local changesets through 2 incoming changesets (11 vs 6 instructions, in 2 conflict groups)
      Integrated 2 changesets out of 2 

       

       

        1. resultsInNull.txt
          0.4 kB
          Sean Brandenburg
        2. incorrect.png
          637 kB
          Sean Brandenburg
        3. correctResult.txt
          0.4 kB
          Sean Brandenburg
        4. correct.png
          1.84 MB
          Sean Brandenburg

            Assignee:
            daniel.tabacaru@mongodb.com Daniel Tabacaru
            Reporter:
            sean.brandenburg@mongodb.com Sean Brandenburg
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: