New_rev when resolving conflicts on Android

Hi,

I have an Android app that uses Couchbase Lite 1.4.0 (SQLite engine), Sync Gateway 1.4.1 & Couchbase Server 4.5.

I’m trying to resolve conflicts on the client. For simulation purposes we have:

db.setMaxRevTreeDepth(2);

This is the detect & resolve conflicts code:

Query query = database.createAllDocumentsQuery();
query.setAllDocsMode(Query.AllDocsMode.ONLY_CONFLICTS);
QueryEnumerator enumerator = query.run();
while (enumerator.hasNext()) {
  QueryRow row = enumerator.next();
  List<SavedRevision> conflictRevs = row.getConflictingRevisions();
  Map<String, Object> latestDocProps = findLatestDocProps(conflictRevs);
  SavedRevision current = row.getDocument().getCurrentRevision();
  for (SavedRevision rev : conflictRevs) {
    UnsavedRevision newRev = rev.createRevision();
    if (rev.getId().equals(current.getId())) {
      newRev.setProperties(latestDocProps);
    } else {
      newRev.setIsDeletion(true);
    }
    newRev.save(true);
}

private Map<String, Object> findLatestDocProps(List<SavedRevision> conflictRevs) {
  Map<String, Object> result = new HashMap<>();
  long lastUpdateTime = 0;
  for (SavedRevision rev : conflictRevs) {
    Map<String, Object> revProps = rev.getUserProperties();
    Long updatedAt = Long.valueOf(revProps.get("updatedAt").toString());
    if (updatedAt > lastUpdateTime) {
      lastUpdateTime = updatedAt;
      result = revProps;
    }
  }
  return result;
}

Basically, the conflict resolution code is copy-paste from the docs. The objective is to resolve the conflicts so that only the most recent document (shown by “updatedAt”) stays.

Here’s the scenario:

  • The document is created and synced with SG
  • The device goes offline
  • The document is updated 5 times (maxRevTreeDepth is 2)
  • The device goes online and conflict is detected
  • The conflict is resolved locally. The document in SG shows property new_rev along with rev. Locally, there are no more conflicts. That seems like a problem, right?

If the following is commented out:

// newRev.setProperties(latestDocProps);

Everything runs just fine. No new_rev in SG and the conflict is resolved locally. Any thoughts on the issue?

Thank you!

Its hard to figure out whats going on without getting more information into the rev tree of the document on SG and on CBL. Can you share the same?
Regardless, during conflict resolution, when you create a new revision with a new set of properties , the parent of that revision must be the rev id of the current revision.
So when you create a new revision (newRev), you should set its _rev to Id of the current revision.

Hi,

All documents are brand new, so they look like normal CBL objects.

Here’s an excerpt of the _sync part of an incorrectly resolved doc:

"_sync": {
    "rev": "7-6385fd83597c90f618cae2773f883124",
    "new_rev": "2-d2d8762ab5d94f272c50f224e4c9257b",
    "flags": 20,
    "sequence": 7,
    "recent_sequences": [
      4,
      5,
      6,
      7
    ],
    "history": {
      "revs": [
        "5-ace784ac863b076fd45f9b5a13c7d56d",
        "6-4bd357936a38e6d66a0a02851900486c",
        "7-6385fd83597c90f618cae2773f883124",
        "2-d2d8762ab5d94f272c50f224e4c9257b",
        "1-6440a2f2330a0b2c66d42023c8adf5c7"
      ],
      "parents": [
        -1,
        0,
        1,
        4,
        -1
      ],
      "deleted": [
        3
      ],
      "channels": [
        null,
        [
          "14e6a0a2-5bed-4730-a1dc-7f9bea3eb953"
        ],
        [
          "14e6a0a2-5bed-4730-a1dc-7f9bea3eb953"
        ],
        [
          "14e6a0a2-5bed-4730-a1dc-7f9bea3eb953"
        ],
        [
          "14e6a0a2-5bed-4730-a1dc-7f9bea3eb953"
        ]
      ]
    },
    "channels": {
      "14e6a0a2-5bed-4730-a1dc-7f9bea3eb953": null
    },
    "time_saved": "2017-06-24T01:16:39.911185452+03:00"
  },

When I log the part with setting properties to the new revision:

if (rev.getId().equals(current.getId())) {
  newRev.setProperties(latestDocProps);
  Log.d("current_rev", current.getId() + " p: " + current.getParentId());
  Log.d("new_rev", newRev.getId() + " p: " + newRev.getParentId());
}

I obtain the following output:

current_rev: 6-4bd357936a38e6d66a0a02851900486c p: 5-ace784ac863b076fd45f9b5a13c7d56d
new_rev: null p: 6-4bd357936a38e6d66a0a02851900486c

Hope that helps somehow. Thank you for your time!