[Couchbase lite 2.8.4] Detect conflict on push (only) replication

Hi all,

Is there any way to detect a conflict during a PUSH (only) replication ? (sync gateway allow_conflict parameter is set with false ) or anything which indicates to the client that the pushed has not beend performed due to a conflict ? (or just rejected by the sync gateway) ?
The custom conflict resolver is not called, and I don’t have any feedback that my local document has not been pushed in the sync gateway.

Regards,

If you get a conflict during push you should be receiving an error in the replicator listener with a conflict error code.

Hello borrrden,

Actually with replication listener I don’t have any data that indicates a conflict. With the document change listener, I can have this information but only one time.

Please find below an extract of my code
    this.replicator.addChangeListener(change -> {
        LOG.info("Status de synchro : " + change.getStatus().toString());
        if (change.getStatus().getActivityLevel() == Replicator.ActivityLevel.STOPPED || change.getStatus().getActivityLevel() == Replicator.ActivityLevel.IDLE) {
            this.refresh();
        }

        if (change.getStatus().getError() != null) {      // never happen
            LOG.error("Error code :  " + change.getStatus().getError().getCode());
            LOG.error("Error message :  " + change.getStatus().getError().getMessage());
            LOG.error("Error trace :  ", change.getStatus().getError());   
        }
    });

    this.replicator.addDocumentReplicationListener(change -> {
        if (!change.getDocuments().isEmpty()) {
            for (final ReplicatedDocument doc : change.getDocuments()) {
                if (doc.getError() != null) {    // <-- happen only the first time
                    final CouchbaseLiteException e = doc.getError();
                    LOG.error("ERREUR DURANT LA REPLICATION : ", e);
                } else {
                    LOG.info("Le document a changé:  " + doc.getID());
                }
            }
        }
    });

During a push where there is a conflict, the ChangeListener Handler never raises an error (ie: change.getStatus().getError() is always null).
Nevertheless, the DocumentReplicationListener handler raises a CouchbaseLiteException on this document (change.getDocuments().get(i).getError() != null) only one time!:

  • first push of a document in conflict => error raised.
    → sync gateway has not been updated (that’s OK)
  • if I proceed to another push replication (without a pull between the two push actions), the error is never raised any more !

So if I don’t pull explicitly between the two push, the information that I have a conflict on this document is lost for the client (I didn’t find any way to retrieve the information after the first push).

Perhaps I’m not clear, so don’t hesitate to say it

Regards,
David

Ok that was my mistake. I couldn’t remember which listener the error came from but the rest sounds correct to me. The pusher is behaving as it should in that it encounters a conflict and does not send that document. Instead it skips it, because conflicts are only resolved via pull. So unless you change the document again you aren’t going to get another notification about it.

1 Like

Hello,

The pusher is behaving as it should in that it encounters a conflict and does not send that document.

and

conflicts are only resolved via pull

I understand and it’s what I expect.

Actually, I think it could be a good thing to permit to the replicator to be notified by this exception until there is no more conflicts on this document…

Jim has explained but here’s a little bit of context on how conflict resolution works

Conflicts are detected on push at the Sync Gateway side. The sync gateway rejects it with a 409 error.

Conflicts are resolved at the time of document save ( and in this case, that would be during replicator pull) and are automatically resolved by the system. You can override it with a custom conflict resolver.

So technically, this means that there are no conflicting revisions of a document in the database. That is by design.

So if you have a push-only replication and a document push is rejected because of a conflict, the local version of the document prevails. In other words, CBL will not keep trying to send up that document just so it can get rejected - it would be very inefficient to do so (remember that the sync gateway receive the document revision and reject it) because it is clear unless an attempt is made by the client to resolve it, the conflicting status of that document will not change.

If you expect conflicts in your system, you must use pushandpull type replication.

1 Like

Hello Priya, thanks for your detailed explanation. It’s what I thought :slight_smile:

If you expect conflicts in your system, you must use pushandpull type replication.
It’s probably what we will do.

Thanks et Regards,
David