Sync. "missing" a document?

I have been playing around with the sync. function to try and get it to reflect the sync that I need (and not least for me to try to understand how it processes the documents both for reads - channels - and for writes - require…).

So I’m getting closer to getting it right :slight_smile:. However, I see some minor differences in the documents on the server and in mobile. I’ve been able to track down an example - and to my best understanding the missing document should also replicate to mobile… So first the document (#159) that does not sync - and another of same type (#159) that does:

FishingClub:159

{
  "sendmailtoreporter": false,
  "enableboastcatches": false,
  "enablerecordcatches": false,
  "enablememberpubliccatches": false,
  "unid": "89A61C8808A7BE13C1257C2000780996",
  "catchesincludephotos": false,
  "catchesshowchart": false,
  "catchesincludenames": false,
  "enablestatistics": false,
  "revisioninfo": {
    "modifiedcount": 0,
    "createdby": "John Dalsgaard/D-D",
    "created": "2013-11-11T22:50:38+0100"
  },
  "type": "FishingClub",
  "externalreporting": false,
  "inactive": false,
  "onlyclubmembers": false,
  "catchesincludebait": false,
  "ispublic": true,
  "name": "Vemb Lystfiskerforening",
  "catchesincludecomments": false,
  "enablegooglechart": false,
  "enablelatestcatches": false,
  "sendmailtoadmin": false,
  "key": "159",
  "mandatoryreporting": false
}

And it’s meta data:

{
  "meta": {
    "id": "FishingClub:159",
    "rev": "1-158fc994b23500000000000002000000",
    "expiration": 0,
    "flags": 33554432,
    "type": "json"
  },
  "xattrs": {}
}

And this one that does sync:

FishingClub:158

{
  "_id": "FishingClub:158",
  "_rev": "1-686e32eb34507db4cb27cfbf1bc669d2",
  "sendmailtoreporter": false,
  "enableboastcatches": false,
  "enablerecordcatches": false,
  "enablememberpubliccatches": false,
  "unid": "99BC661C72404CA4C1257C2000780995",
  "catchesincludephotos": false,
  "catchesshowchart": false,
  "catchesincludenames": false,
  "enablestatistics": false,
  "revisioninfo": {
    "created": "2013-11-11T22:50:38+0100",
    "createdby": "John Dalsgaard/D-D",
    "modifiedcount": 0
  },
  "type": "FishingClub",
  "externalreporting": false,
  "inactive": false,
  "onlyclubmembers": false,
  "catchesincludebait": false,
  "ispublic": true,
  "name": "Vejle Sportsfiskerforening",
  "catchesincludecomments": false,
  "enablegooglechart": false,
  "enablelatestcatches": false,
  "sendmailtoadmin": false,
  "key": "158",
  "mandatoryreporting": false
}

And it’s meta data:

{
  "meta": {
    "id": "FishingClub:158",
    "rev": "6-15cd3f528c9900000000000002000000",
    "expiration": 0,
    "flags": 33554432,
    "type": "json"
  },
  "xattrs": {
    "_sync": {
      "rev": "1-686e32eb34507db4cb27cfbf1bc669d2",
      "sequence": 122704,
      "recent_sequences": [
        122704
      ],
      "history": {
        "revs": [
          "1-686e32eb34507db4cb27cfbf1bc669d2"
        ],
        "parents": [
          -1
        ],
        "channels": [
          [
            "!"
          ]
        ]
      },
      "channels": {
        "!": null
      },
      "cas": "0x0000998c523fcd15",
      "value_crc32c": "0x17fc2714",
      "time_saved": "2019-10-11T00:46:46.841427353+02:00"
    }
  }
}

They are both public documents ("ispublic": true) and that should make them both replicate (according to the sync. function below).

I have tried to take the database offline and do a resync - it makes no difference.

I have searched the log files:

grep "FishingClub:158" sg_info.log 
2019-10-13T18:37:19.643+02:00 [INF] Javascript: Sync SG: doc id: FishingClub:158, ispublic: true, userkey=undefined,  creation
2019-10-13T18:37:19.643+02:00 [INF] Javascript: Sync SG: public, id: FishingClub:158
grep "FishingClub:159" sg_info.log 
grep "FishingClub:158" sg_warn.log 
grep "FishingClub:159" sg_warn.log 
grep "FishingClub:158" sg_error.log 
grep "FishingClub:159" sg_error.log 

As you can see there is only mentioning of the one that replicates Ok - no mentioning of the other in any of the logs…

Finally, here is my sync. function:

function (doc, oldDoc) {
    function _log(t) {
        // Write to sg_info.log
        console.log('SG: ' + t);
    }
    function _getUserKey(d) {
        var key = null;
        if (d) {
            if (d.type == 'User') {
                key = d.key;
            } else {
                key = d.userkey;
            }
        }
        return key;
    }

    if (doc && doc._deleted) {
        // Doc. deleted -> if public then require
        if(oldDoc){
            var userkey = _getUserKey(oldDoc);
            _log('delete doc id: ' + doc._id + ', userkey=' + userkey);
            if (userkey != null) {
                requireUser(userkey);
            } else {
                requireAdmin();
            }
        }
        _log('doc deleted, id: ' + (doc._id || 'no id!') + ', ' + (oldDoc ? ('old key=' + oldDoc.key + ', userkey=' + userkey) : 'no oldDoc'));
        return;
    }
    _log('doc id: ' + (doc._id || 'no id!') + ', ispublic: ' + doc.ispublic + ', userkey=' + userkey + ', ' + (oldDoc ? (oldDoc._deleted ? 'oldDoc is deleted' : ('old key=' + oldDoc.key + ', oldDoc.userkey=' + oldDoc.userkey + ' update')) : ' creation'));
    // Document type is mandatory
    if (typeof doc.type === 'undefined') {
        _log('Document type missing: ' + JSON.stringify(doc));
        throw ({ forbidden: "Document type is required. id=" + doc._id });
    }
    // Document key is mandatory
    if (typeof doc.key === 'undefined') {
        _log('Document key missing: ' + JSON.stringify(doc));
        throw ({ forbidden: "Document key is required. id=" + doc._id });
    }
    // Update: Cannot allow change of type or key
    if (oldDoc != null && !oldDoc._deleted) {
        // Update
        if (oldDoc.type != doc.type) {
            throw ({ forbidden: "Can't change doc type" });
        }
        if (oldDoc.key != doc.key) {
            throw ({ forbidden: "Can't change doc key" });
        }
    }
    // Document sync is disabled (used for type Image)
    if (doc.issyncdisabled) {
        throw ({ forbidden: "Sync. disabled for id=" + doc._id });
    }
    // All public docs are available in the app
    if (doc.ispublic) {
        _log('public, id: ' + (doc._id || 'no id!'));
        channel('!');
    }
    // All non-club/-assoc fishing trips and catches are available (for stats)
    if ((doc.type == 'FishingTrip' || doc.type == 'Catch') && doc.userkey) {
        _log('non-club/-assoc trip/catch, id: ' + (doc._id || 'no id!'));
        channel('!');
     }
    // All users are available (for stats)
    if (doc.type == 'User') {
        _log('User doc, id: ' + (doc._id || 'no id!'));
        channel('!');
     }

    // Allow anyone to create a Feedback or Observation on the server
    if (oldDoc == null && doc.userkey == null && (doc.type == 'Feedback' || doc.type == 'Observation')) {
        _log('Created ' + doc.type + ': ' + (doc._id || 'no id!') + ', key: ' + doc.key + ' as anonymous user ');
        return;
    }

    // Only non-public docs "owned" by user can be created/updated (and replicated)
    var userkey = _getUserKey(doc);
    if (userkey != null) {
        if (oldDoc != null && ! oldDoc._deleted) {
            // Update
            if (oldDoc.userkey && oldDoc.userkey != doc.userkey) {
                throw ({ forbidden: "Can't change user key" });
            }
        }
        _log('User owned, id: ' + (doc._id || 'no id!') + ', type: ' + doc.type + ', user: ' + userkey);
        channel('channel.' + userkey);
        access(userkey, 'channel.' + userkey);
        requireUser(userkey);
    } else if (doc.ispublic) {
        requireAdmin();
    } else {
        // Creation/update without user
        _log('Document type cannot be created without user key: ' + (doc.type === 'Image' ? doc._id : JSON.stringify(doc)));
        throw ({ forbidden: "This document type cannot be created without user key. id=" + doc._id });
    }
 }

And for completeness I have also included the import filter - just to show that it shouldn’t have any impact of this issue:

            function(doc) {
               // Some document types not allowed on mobile
               if (doc.type == 'EnvLake' || doc.type == 'EnvMeasurement' || doc.type == 'ActivityLog' || doc.type == 'Feedback' || doc.type == 'Image') {
                return false;
                }
                if ((doc.type == 'FishingTrip' || doc.type == 'Catch') && typeof doc.clubonlykey !== 'undefined' && doc.clubonlykey != '') {
                    return false;
                }
                return true;
            }

How can I debug this issue? Is there any way a can “clean” the history and get the sync. gateway to resync ? What could be the reason that “FishingClub:159” does not replicate???

I could not figure out a way to solve this…

So I ended up flushing the bucket, restoring the database from production, rebuild all indexes, recreate all sync.users from db, and finally do a resync on sync.gateway.

It has taken quite some time to do that (bucket has 450K docs) - and would not be possible in a production environment.

Therefore, I’m still curious about possible explanations - and ways to solve it… Would be nice to know should a similar problem happen in production some time…

… and just for the record everything seems to be aligned now :+1: