Has anyone else had the Sync Gateway admin web UI go strange at times?

I dunno what causes it, and I’m not sure I can reliably fix it.
Here’s what it looks like when it goes strange:

  • The documents display shows “0 documents”. If I enter a document Id - I get “Loading” but the document never shows. If I enter the document Id into the couchbase UI - the document is there (see second image).
  • The sync function shows “loading” but never finishes (see first image). The sync function is not shown.
  • Channels is empty (shows “0 channels”) when I know I have a ton
  • Users works fine.

A reboot of the server (ubuntu) doesn’t fix it. Reloading the page
without a cache doesn’t seem to help.

I don’t have that much data in my test DB - about 25k docs.
I did delete all data from the couchbase bucket - and that seems to fix
things sometimes.

This doesn’t impact the operation of the sync gateway - it syncs multiple clients perfectly and the REST API works fine.

Not a biggie - just very strange.

Thanks for any advice.
Paul


My experience is that it often makes the whole browser unresponsive when loading a document. Hence I stopped using it

Can you provide the sync function used on this instance?

James

@jamiltz
Sure… I’ve copied it below.
I did notice that this problem only started happening when our sync function
started to get a bit bigger. A couple of times it went away if I emptied the function,
but not always I think.

Thanks.
Paul.

function(doc, oldDoc) { 
	console.log("Starting sync function");

	//  For update/create - check the required data fields
	if (!doc._deleted) {
		console.log("Update/Create checking required fields");

		//	Document type is mandatory
		if (!doc.type) 
			throw({forbidden: "Document type is required."});

		//	Channels are mandatory as they set access rights.
		if (!doc.channels)
			throw({forbidden: "Document channels are required."});

		//	If this is a user record... make sure the user keeps access to their own record
		if (doc.type == "User")
			if (doc.channels.indexOf(doc._id) == -1)
				throw({forbidden: "Cannot remove access to own User record"});

		//	Book and PublicUser require an owner
		if (doc.type == "Book" || doc.type == "PublicUser")
			if (!doc.owner) 
				throw({forbidden: "Books and PublicUser require owner field"});


		//	Version is mandatory so we can change data structure if required.
		//	if (!doc.version) {
		//		throw({forbidden: "Document version is required."});
		//	}
	
	}

	//    For deletion/update... the following permissions are required
	//	Note - it might be that oldDoc != null is not a good test for delete/update.
	if (oldDoc != null) {
		console.log("Deletion/Update permission check");
		//	Only owners can modify/delete books and public key components.
		if (oldDoc.type == "Book" || oldDoc.type == "PublicUser")
			requireUser(oldDoc.owner);
	
		//	Only the user themselves can modify their own user record.
		if (oldDoc.type == "User" )
			requireUser(oldDoc._id);  
	
		//    Anyone with channel access can modify/delete sections and notes
		if (oldDoc.type == "Section" || oldDoc.type == "Notes")
			requireAccess(oldDoc.channels);
	
	} else {
		console.log("Creation permission check");
		//	For create (oldDoc == null)... the following permissions are required

		//	Only owners can create their own books and public components.
		if (doc.type == "Book" || doc.type == "PublicUser")
			requireUser(doc.owner);
	
		//	Only the user themselves can create their own user record.
		if (doc.type == "User" )
			requireUser(doc._id);  
	
		//    Anyone with channel access can create sections and notes
		//	Reason is that when you add a note/section to a book that YOU DONT OWN,
		//	the owner of the section/note MUST be the book owner
		if (doc.type == "Section" || doc.type == "Notes")
			requireAccess(doc.channels);
	
	}

	console.log("Checking document type change");
	//	For any update - make sure that the type field cannot be changed
	if (oldDoc != null && !doc._deleted)
		if (doc.type != oldDoc.type)
			throw({forbidden: "Document type cannot be changed."});
	
 

	console.log("All data/permission checks passed");

	//	If we get to this point... we are happy with the data and permissions.

	//	If a user is being updated - we reset channels (books) that the user can access.
	if (!doc._deleted && doc.type == "User") {
		console.log("Updating access ", doc._id, doc.channels);
		var book_ids = Object.keys(doc.book_keys);
		access(doc._id, book_ids);
	}		
	console.log("Updating channels", doc.channels);

	//	Set the channels that this doc belongs to.
	channel(doc.channels); 
}

Thanks. Yes there’s a known issue in how the sync function is executed in the admin UI.

  • In the admin UI, oldDoc is false when there is no parent revision.
  • When executed by Sync Gateway, oldDoc is null when there is no parent revision.

So in your sync function, you check if there is a parent like so:

if (oldDoc != null) {

And so that statement becomes:

  • false != null which is true in the Admin UI
  • null != null which is false when executed by Sync Gateway.

To get around this problem you can check for either condition ((oldDoc == false) || (oldDoc != null)). See this code snippet for an example https://developer.couchbase.com/documentation/mobile/current/training/develop/adding-security/index.html#document-types

As you’ve mentioned previously, the issue only occurs in the browser and so doesn’t impact the normal operations but can be quite surprising during development. The admin UI isn’t an official feature (i.e it’s not being actively worked on or maintained) and so that’s why there are these kind of nasty bugs around. But a handy tool during development nonetheless.

1 Like

I made the changes per the linked document, including the use of isCreate(), isUpdate(), isDelete() etc. Restarted sync_gateway and the UI started working again (Documents, Sync, Users and Channels).

Brilliant! Thanks for your help.

It might not be an official tool, but that web UI is pretty handy for a quick check of certain data.

Cheers.
Paul