Trying to understand error: "Exception in JS sync function"

385 views
Skip to first unread message

Christoph Berlin

unread,
Nov 17, 2014, 7:02:21 PM11/17/14
to mobile-c...@googlegroups.com
Hello again,

I am sure this is something we caused internally - I just don't know what. :(

Scenario: we are currently building a product and during the development phase we need to periodically delete all documents for testing. We therefore implemented a quick and dirty delete function that simple wipes all existing documents in the database. We cannot just delete the local data as the changes would replicate down from the remote database again. However when running the delete function it seems that something causes the sync gateway to throw the following error:

10:23:59.477 WARNING: CBL_Pusher[http://sync.dev.appmonkie.com/default]: _bulk_docs got an error: {

    error = 500;

    id = "account:te...@test.com";

    reason = "Exception in JS sync function";

    status = 500;

}


From this moment on synchronization doesn't work anymore - with the every push the same error occurs. Only when deleting the local database (mobile device) we can start the replication but then it seems that the remote documents are still there. In a nutshell it seems that the delete function causes a conflict in the database and prevents the changes to be pushed upstream. Looking at the sync gateway logs it seems that the gateway has issue with the channels. My theory is that due to the deletion of the documents the channel is invalidated but I am not sure whether this would cause this error.


Sync Gateway:

19:48:21.848881 HTTP:  #2064: POST /default/_bulk_docs  (as te...@test.com)

19:48:21.851336 WARNING: Sync fn exception: TypeError; doc = map[owner:te...@test.com _id:account:te...@test.com created_at:2014-11-17T19:48:21.309Z name:Test _revisions:map[ids:[ca9dbffd62a5728a5317ecadbe96c1c6 50b6701430f66b36be95eb866d4d5137] start:%!s(float64=19)] status:new _rev:19-ca9dbffd62a5728a5317ecadbe96c1c6 type:account updated_at:2014-11-17T19:48:21.309Z] -- db.(*Database).getChannelsAndAccess() at crud.go:715


Excerpt from gateway config:

else if (doc.type == "account")
                        {
                                var username = doc._id.substring(doc._id.indexOf(":")+1);
                                channel("account-"+username);
                                if (!doc.owner)
                                {
                                        throw({forbidden : "account must have an owner"})
                                }
                                if (oldDoc)
                                {
                                        var oldOwnerName = oldDoc.owner.substring(oldDoc.owner.indexOf(":")+1);
                                        requireUser(oldOwnerName)
                                }
                                // set access permissions for owner and members
                                var ownerName = doc.owner.substring(doc.owner.indexOf(":")+1);
                                access(ownerName, "account-"+username);
                                if (Array.isArray(doc.members))
                                {
                                        var memberNames = [];
                                        for (var i = doc.members.length - 1; i >= 0; i--)
                                        {memberNames.push(doc.members[i].substring(doc.members[i].indexOf(":")+1))};
                                        access(memberNames, "account-"+username);
                                }
                        }

Delete function:

CBLQuery *query = [[OPDatabase getSharedDatabaseInstance].dataBaseInstance createAllDocumentsQuery];

    CBLQueryEnumerator *result = [query run:nil];

    for (CBLQueryRow *row in result)

    {

        NSError *error;

        NSLog(@"Deleting doc id: %@", row.documentID);

        [row.document deleteDocument:&error];

        if (error) NSLog(@"Error: %@", error.userInfo);

    }


Please keep in mind that this function is only for dev purposes and not really important - but it would be great to understand what is happening here.

Thanks as always Christoph

Jens Alfke

unread,
Nov 17, 2014, 7:31:23 PM11/17/14
to mobile-c...@googlegroups.com

> On Nov 17, 2014, at 4:02 PM, Christoph Berlin <hoptoawe...@gmail.com> wrote:

> However when running the delete function it seems that something causes the sync gateway to throw the following error:

It looks as though your sync function doesn't properly handle deletions and throws a JavaScript TypeError exception. It's not immediately obvious to me what the error in the sync function is; using the log( ) function can help you troubleshoot it.

Deletions can be a bit tricky to handle because the regular deleteDocument method replaces the body of the document with nothing but a "_deleted":true property — so there's no "type", or any of your other properties. In some cases for correct validation you may need to delete the document by explicitly setting "_deleted":true without removing the other properties; you can do this by creating a new CBLRevision, setting its deletion property to YES, and saving it.

—Jens

Todd Freese

unread,
Dec 17, 2014, 8:21:13 PM12/17/14
to mobile-c...@googlegroups.com
I'm running into this now as well.

My sync function checks one of my properties called "owner". But since I'm using deleteDocument that property is gone and get the exception in JS sync function error.

Seems like just setting the _deleted prop myself solves the problem. But I would rather not have all the props still in the tombstone.

Would it make sense to have a deleteDocument method that you could pass in a list of props to carry over into the tombstone? I would think that a lot of devs using SG would run into this problem.

Todd

Todd Freese

unread,
Dec 17, 2014, 8:51:16 PM12/17/14
to mobile-c...@googlegroups.com
D'oh!

Just found the propertiesToSaveForDeletion method!

T

Jens Alfke

unread,
Dec 18, 2014, 11:34:30 AM12/18/14
to mobile-c...@googlegroups.com

> On Dec 17, 2014, at 5:51 PM, Todd Freese <to...@filmworkers.com> wrote:
>
> Just found the propertiesToSaveForDeletion method!

:) Yeah, I ran into the same issue while working on a side-project app earlier this year, so I added that property…

—Jens
Reply all
Reply to author
Forward
0 new messages