Strange behavior with sync gateway and channels

Hi there,

I’m looking for advice or tips to what to look for.

I have sync gateway (2.7) with the following sync configuration :

"db-prod": {
      "server": "http://172.18.64.81:8091",
      "bucket": "pulse",
      "username": "**",
      "password": "****",
      "enable_shared_bucket_access": true,
      "import_docs": true,
      "num_index_replicas": 0,
      "allow_conflicts": false,
      "revs_limit": 20,
      "users": {
        "GUEST": { "disabled": true, "admin_channels": ["*"] },
        "sync_g_user": {"password": "***", "admin_channels":["*"] }
      },
      "sync": `function (doc, oldDoc) {
          if (doc.type === 'pulseAgency' && doc.ageInternalCode) {
              access("sync_g_user", doc.ageInternalCode);
          }
          if (doc.sysSyncActive && doc.sysSyncChannel) {
              channel(doc.sysSyncChannel);
          }
      }`
  }
}

The doc.sysSyncChannel is an array of strings (ie : [“demo”, “pls69t”]…)

We then have CBL on android and ios (2.8.0). When a user log in on the mobile app, we set up the replication this way :

ReplicatorConfiguration config = new ReplicatorConfiguration(database, targetEndpoint);
// Limitation au channel de l'utilisateur
config.setChannels(Collections.singletonList(syncChannel));
config.setContinuous(true);
config.setReplicatorType(ReplicatorConfiguration.ReplicatorType.PUSH_AND_PULL);
// Authentification
config.setAuthenticator(new BasicAuthenticator(syncUsername, syncPassword));
replicator = new Replicator(config);

The syncChannel option being a string, like “demo”, or “pls69t”. One user can only set up replication for one channel. The only way to set up replication for another channel is to uninstall and reinstall the mobile application.

We have been using this configuration for almost 2 years now, and everything was fine.

Recently, we had a synchronization problem with 2 users : for the first user, on iOS, using the channel “channel1” for example, he had documents for “channel1”, but found also documents for another channel. We know for sure thoses documents always had their channels, and those never changed. The strange thing is that this was not a mixup between several channels, but only between 2.

The second user had the same problem, but with 2 other channels, and on Android.

My question is : where should I look ? I don’t know if this is something wrong in our code, on the mobile application or on the sync gateway configuration, or if for a reason I don’t understand sync gateway somethings mixes things up ? Is it possible ?

Tell me if you need more informations or details regarding this.

Thanks a lot
Jérémie

@jeremieburtin , based on your sgw config, I see that you gave access to all channel to sync_g_user.
In sync function, in 2nd if condition, it assigns to two channels i.e “demo”, “pls69t” which is expected.
When you create docs through iOS or Android, you might see docs access to other channels as docs are processing through sync function and it assigns to 2 channels if it has sysSyncActive and sysSyncChannel.

Is it possible to provide the content of the doc created from iOS and Android? It depends on what doc body it has and it process the sync function. If you cannot, if you can provide sample test docs which can process through sync function is fine. Basically matching with channels and doc.type, doc.sysSyncActive content.

Hi, thanks for your answer !

I may have not been precise enough :slight_smile: My documents are first created on an API, in couchbase server, and then synced on the mobile application through sgw and couchbase lite.

Here are examples :

{
  "fullName": "Jérémie BURTIN",
  "id": "OAuthUser::gi3af3cbaef709f1e11e99f9a9f5af5cf496e",
  "mobile": "****",
  "orgHoldingcode": "PIX73",
  "passwordResetToken": "117728",
  "passwordResetTokenDate": "2021-01-29T12:14:17Z",
  "professional": "*****",
  "profilType": "agency",
  "sysActive": true,
  "sysCredate": "2019-07-05T12:13:02Z",
  "sysCrelog": "OAuthUser::S00002",
  "sysModdate": "2021-03-03T08:44:26Z",
  "sysModlog": "OAuthUser::S00001",
  "sysSyncActive": true,
  "sysSyncChannel": [
    "hsem1",
    "demo"
  ],
  "type": "OAuthUser",
  "username": "jeremie@*****",
  "usrAgencyAccess": [
    {
      "ageAdminSettings": true,
      "ageDefault": true,
      "ageId": "pulseAgency::S00001",
      "ageInternalCode": "hsem1",
      "ageProfil": "secretary",
      "color": "#ff8f00",
      "mftCategories": [
        "respiratory",
        "drip",
        "nutrition",
        "insulin",
        "incontinence",
        "stoma"
      ]
    },
    {
      "ageAdminSettings": true,
      "ageDefault": false,
      "ageId": "pulseAgency::S00002",
      "ageInternalCode": "demo",
      "ageProfil": "accountant",
      "color": "#ffab91",
      "mftCategories": [
        "respiratory",
        "drip",
        "nutrition",
        "insulin",
        "incontinence",
        "stoma"
      ]
    }
  ],
  "usrOrganizations": [
    {
      "orgAdminSettings": true,
      "orgId": "pulseOrganization::S00001",
      "orgName": "ORG"
    }
  ],
  "usrWarehouseAccess": [
    {
      "warDefault": true,
      "warId": "pulseWarehouse::S00001",
      "warName": "Entrepôt principal"
    }
  ]
}

And another document :

{
  "id": "OAuthUser::S00002",
  "sysActive": true,
  "sysCredate": "2018-12-11T20:00:00Z",
  "sysCrelog": "import",
  "sysSyncActive": true,
  "sysSyncChannel": [
    "pls69t"
  ],
  "type": "OAuthUser",
  "sysModdate": "2020-01-31T09:05:34Z",
  "sysModlog": "OAuthUser::S00001",
  "fullName": "David M",
  "profilType": "agency",
  "username": "david@***",
  "usrAgencyAccess": [
    {
      "ageId": "pulseAgency::S00003",
      "ageDefault": true,
      "ageInternalCode": "pls69t",
      "ageProfil": "manager",
      "mftCategories": [
        "insulin",
        "drip",
        "respiratory",
        "nutrition",
        "incontinence",
        "stoma",
        "bandage"
      ],
      "color": "#c62828"
    }
  ],
  "usrOrganizations": [
    {
      "orgId": "pulseOrganization::S00003",
      "orgAdminSettings": true,
      "orgInternalCode": "ORG3"
    }
  ],
  "orgHoldingcode": "PIX69",
  "passwordResetToken": "113145",
  "passwordResetTokenDate": "2020-01-11T12:59:04Z"
}

The problem appears to be, sometimes when the first synchronization is initialized on mobile, using the hsem1 channel, some documents with the pls69t channel are synced too. Those documents never had the hsem1 channel. I don’t know if it’s something wrong on my side or if this is a sgw/cbl bug ?

Thanks !
Jérémie

There are some obvious problems with your config. Sridevi alluded to them. While fixing them itself may not fully resolve the issue, I think its important to start with the right config and I will then provide some troubleshooting tips.

  1. With this line, you are statically granting the user access to the star channel and thereby granting user access to all documents in the database which is not what you wanted. So the “access()” call that you have within your sync function is irrelevant . In fact, it’s expensive processing overhead at this point. So fix this line so you do not grant access to the star channel.

Once you fix the above issues, the first one in particular, create or update documents and see what happens . You cannot retroactively do anything about documents that have already been pulled by the clients.

Here are some tips. Channels determine access control so you need to ensure thats set up correctly

  • Check the output of _raw REST endpoint on sync gateway for each document. See the channels that the document have been assigned to and confirm that it is in fact assigned to right channel.

  • Output the user details via user endpoint and confirm that user has only access to the specified channels and nothing more

  • Output the replicator config on CBL to confirm that the channel filters are set up correctly

On unrelated note, there is another issue with your config. Not sure of the server version you are using but the http:8091 way of bootstrapping is very old. Our recommended option is to use couchbase scheme which will use the newer bootstrap protocol. So update your config to use the updated endpoint

Thanks @priya.rajagopal for your response.

So if I understand correctly, I should have the following configuration for my user :

 "sync_g_user": {"password": "***", "admin_channels":["default"] }

There are no documents in the default channel.

We can keep the sync function as follow:

"sync": `function (doc, oldDoc) {
          if (doc.type === 'pulseAgency' && doc.ageInternalCode) {
              access("sync_g_user", doc.ageInternalCode);
          }
          if (doc.sysSyncActive && doc.sysSyncChannel) {
              channel(doc.sysSyncChannel);
          }
      }`

We are using the access() function because our channels list is not static, this is the way we found to add access to sync_g_user to the created channels.

And for the "server": "http://172.18.64.81:8091",, we simply used the documentation (we set it up like more than 2 years ago). But we’ll change it, following your advice.

I’ll let you know when we’ll have changed according what you said.

Thanks again
Jérémie

No, it should be

"sync_g_user": {"password": "***" }

Since you are dynamically assigning the channels to user, you do not need to do any static assignment

Okay.

When we’ll restart sgw after updating the configuration, does the sync function checks all the documents again ? My question behind this is : will the sync_g_user still have access to the channels created with the documents having doc.type === 'pulseAgency' ? Or will it loose the access until it sees again those documents ?

Thanks
Jérémie

No. That would be a very expensive operation and for most part, it wouldn’t be very useful. In your case, you can manually trigger a resync as detailed here or update the access grant document (for instance- update a sentinel value like a counter) so it is processed by the sync gateway again .

We’ll have a maintenance operation on our infrastructure this week end, i’ll tell you how it went with this point. Thanks again.

One side question : in Couchbase Server, there is a "sg_allDocs_x1 " index. Is it linked to the “*” channel I have in my configuration ? When I’ll have deleted this channel in my configuration, can I delete this index ?

Thanks !
Jérémie

You can’t. The allDocs index is used by other operations (including the _resync functionality). Note that even if none of the users configured have access to the star channel - that is a system channel that is automatically created and holds all documents. So it exists even if the users you define are not granted access.
You can disable the star channel if you want to but you cannot get rid of the index.