Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SyncFunc: oldDoc parameter is always null #7182

Open
dangrieshaber opened this issue Nov 6, 2024 · 6 comments
Open

SyncFunc: oldDoc parameter is always null #7182

dangrieshaber opened this issue Nov 6, 2024 · 6 comments

Comments

@dangrieshaber
Copy link

Checking any value against the old document fails as the oldDoc parameter is always null.

Sync Gateway version

Couchbase Sync Gateway/3.2.0(514;release) CE

Operating system

Windows (all versions)

Expected behavior

oldDoc contains a reference to the changed document in its previous state

Actual behavior

oldDoc parameter is null

Steps to reproduce

  1. Create Sync Function that checks the null-state of oldDoc parameter
  2. Update a document relevant for sync
  3. oldDoc value is null in SyncFunc
@exinarium
Copy link

Getting the same behaviour when syncing down docs that need to compare the old doc to the new doc using the sync function. Has this received any attention as of yet? Is a fix on the way or an alternative version that I can use?

@torcolvin
Copy link
Collaborator

The sync function is only run when documents are updated. You mentioning syncing down documents, but the sync function is not populated. This functionality is not generally broken in Sync Gateway 3.2.0.

Can you provide database configuration and the recipe for how you are updating the documents?

@dangrieshaber
Copy link
Author

In reproducing the error, the sync function is actually executed as expected when a document is updated, e.g. from CB web UI.
The issue is that the oldDoc parameter of the Sync Function is always null:

{
    "bucket": "TestBucket",
    "scopes": {
        "TestScope": {
            "collections": {
                "TestCollection": {
                    "sync": "function(doc, oldDoc, meta) { console.log(oldDoc); //is always null }"
                }
            }
        }
    },
    "name": "testdatabase",
    "revs_limit": 20,
    "import_docs": true,
    "allow_empty_password": false,
    "enable_shared_bucket_access": true,
    "allow_conflicts": true,
    "num_index_replicas": 0,
    "guest": {
        "disabled": true
    }
}

@torcolvin
Copy link
Collaborator

As per https://docs.couchbase.com/sync-gateway/current/import-processing.html#operation, when importing a document from Couchbase Server the contents of oldDoc will always be nil.

If a document is updated via the REST api or a Couchbase Lite mutation, then the oldDoc will be populated.

@dangrieshaber
Copy link
Author

Thanks for the prompt reply.
I mistook Import processing to be separate from sync/replication due to document mutation (also via CB Server).

That is great pity. Any chance this might change?

Our use-case is to purge documents from CB Lite when a channel was removed from a document.
I'm fully aware of the built-in auto-purge when access is revoked, but our scenario is different and does not offer opportunity to use this.

The basic idea is this:

  • Client replicator subscribes to channels ["a", "b", "c"]
  • Doc 'AA.channel` holds the following sync channels, e.g. ["c", "d", "e"]
  • Channel "c" is shared, so the document is replicated to the client
  • Let's say channel "c" gets removed on the server
  • In the sync func, doc.channels will now be ["d", "e"], while oldDoc.channels is ["c", "d", "e"] (or, so I hoped)
  • When calling channel() in the sync function, oldDoc.channels is included, causing channel "c" to be synced on last time
  • The client is still subscribed to channel "c", resulting in the doc being replicated
  • Client-side, a custom DocumentReplicationListener will compare the received document's channels ["d", "e"], to the subscribed channels ["a", "b", "c"]. Now, there is no intersect and the document is subsequently purged locally
function(doc, oldDoc, meta) {
    var newChannels = doc.sync && doc.sync.channels ? doc.sync.channels : [];
    var oldChannels = oldDoc && oldDoc.sync && oldDoc.sync.channels ? oldDoc.sync.channels : [];
    
    channel(newChannels);
    channel(oldChannels);
}

@bbrks
Copy link
Member

bbrks commented Dec 11, 2024

  • When calling channel() in the sync function, oldDoc.channels is included, causing channel "c" to be synced on last time
  • The client is still subscribed to channel "c", resulting in the doc being replicated
  • Client-side, a custom DocumentReplicationListener will compare the received document's channels ["d", "e"], to the subscribed channels ["a", "b", "c"]. Now, there is no intersect and the document is subsequently purged locally

Hi,
I think there may be a misunderstanding of channels and removal replication.
The root of your problem appears to be that you're assigning current document channels based on oldDoc.channels - this isn't nessesary and SG/CBL will get the channel removal replicated, even with .

Are you reliant on other behaviour of channels(oldDoc.channels)? Or is this to just try and get removals replicated to clients by using the document listener? Do your replicators have channel filters set?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants