[Couchbase lite 2.8.4] Merge conflict resolver never called

Hi all,

I’m trying to create a custom conflict handler for managing conflicts during a client update between sync gateway and a couchbase lite but the merge resolver is neved called.
The sequence of action is as follows:

  • Sync gateway has a document in revision 1
  • client A and client B have this document in revision 1 on their couchbase lite database
  • client A pushed this document in revision 2 in the sync gateway
  • client B update localy this document (database.save)
  • client B perform a pull action to the sync gateway
    —> I thought the resolver was going to be called but not. Is it normal? Where is my error ? (please find below the environment, config and code)

Other question : Can you confirm that the conflict resolver function in the sync gateway is only during inter sync gateway replication and it’s not involved in this case?

Environment :

  • couchbase server : 7.0 (enterprise)
  • sync gateway : 2.8 (enterprise) - allow_conflict parameter is set to false
  • couch base lite : 2.8.4 (enterprise)

Resolver code (java):
public class MergeConflictResolver implements ConflictResolver {
public Document resolve(Conflict conflict) {
Map<String, Object> merge = conflict.getLocalDocument().toMap();
merge.putAll(conflict.getRemoteDocument().toMap());
LOG.info(“conflict resolver called !”);
return new MutableDocument(conflict.getDocumentId(), merge);
}
}

Application code : (java)
CouchbaseLite.init();
final DatabaseConfiguration config = new DatabaseConfiguration();
config.setDirectory(" a full path ");
final String bucket = “”;
final Database database = new Database(bucket, config);
try {
String json = < read the content a json file >
final Map<String, Object> data = new Gson().fromJson(json, new TypeToken<HashMap<String, Object>>() { }.getType());
final MutableDocument doc = new MutableDocument(data);
final Query queryDoc = QueryBuilder.select();
for (final Result thisDoc : queryDoc.execute()) {
final MutableDocument docToUpdate = database.getDocument(thisDoc.getString(“id”)).toMutable();
docToUpdate.setData(data);
if (!database.save(docToUpdate, (newDoc, curDoc) → {
// manage local save database conflict
if (curDoc == null) {
return false;
}
final Map<String, Object> dataMap = curDoc.toMap();
dataMap.putAll(newDoc.toMap());
newDoc.setData(dataMap);
return true;
})) {
LOG.error(“error during update local database”);
}
} catch (final JsonSyntaxException e) {
LOG.error("Error ", e);
} catch (final IOException e) {
LOG.error("Error ", e);
}
}

final Endpoint targetEndpoint = new URLEndpoint(new URI(SYNC_GATEWAY_URL + bucket));
final ReplicatorConfiguration replConfig = new ReplicatorConfiguration(database, targetEndpoint);
replConfig.setConflictResolver(new MergeConflictResolver());
if () {
replConfig.setReplicatorType(ReplicatorConfiguration.ReplicatorType.PULL);
} else if () {
replConfig.setReplicatorType(ReplicatorConfiguration.ReplicatorType.PUSH);
}
replConfig.setAuthenticator(new BasicAuthenticator(DB_USER, DB_PASS));
final Replicator replicator = new Replicator(replConfig);
replicator.addChangeListener(change → {
if (change.getStatus().getError() != null) {
LOG.error("Error code : " + change.getStatus().getError().getCode());
}
});
replicator.start();

// rest of the application

I don’t understand why the merge resolver is never called … It’s likely a mistake in my code (or comprehension) but I don’t know where …

A precision : if the client B try to push the local document to the sync_gateway, the push is not performed and the document in the sync gateway is still the document from the client A.

Custom Conflict Resolver works very well (and the implementation I gave as well)
I had an issue on my channel definition configuration (in one client) which misled me.

So, there is no issue.