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 …