couchbase/couchbase-lite-ios

Occasionally run into “connection closed abnormally” problem

zyphs21 opened this issue · 15 comments

Describe the bug

My ReplicatorConfiguration is

.replicatorType = .pull
.continuous = true

In replicator.addChangeListener's ReplicatorChange block sometimes got the error:

connection closed abnormally

When this error happen, CouchBase won't push the changes to the server until another changes happen.

**Platform **

  • Device: iPhoneXR and others
  • OS: iOS 13.3.1
  • Couchbase Version CouchbaseLiteSwift 2.7.0
  • Synch Gateway Version Sync Gateway 2.6.0

Are you sure the SG was connected during the whole time? as well the device network status didn't change? I saw this happens when any connection issue happens.

if connection closed abnormally happens, how can we let CouchBase continue to push the changes to the server ? Are there any retry times?

Websocket connection closed abnormally(1006), is a transient error. For transient errors, if you are using a one-shot replicator, it will retry two times before giving up, and for a continuous replicator, it will keep retry indefinitely. Retry interval will keep increasing exponentially, for e.g., 2secs, 4secs, 8secs, etc.. with a maximum of 10mints.

https://docs.couchbase.com/couchbase-lite/2.7/swift.html#handling-network-errors

Closing this, looks like we taken care of the problem.

Hello, Thank you for your help.

Reference from CouchBaseLite Dos: handling-network-errors:

When a permanent error occurs (i.e., 404: not found, 401: unauthorized), the replicator (continuous or one-shot) will stop permanently.

When the replicator stop permanently, How can we restart it again? Could we simply create a new Replicator and execute replicator.start() ?

Is there any permanent errors causing replicator to stop permanently? Could we just only use 404 and 401 as the judgement ?

Ideally restarting or retrying won't help you to recover from a permanent failure. Any error which are not transient can be considered permanent, and list of transient error codes also can expand. For the transient errors, replicator has its own retry logic, so don't bother the duplicate error handling on app side.

Curious whats the scenario you are trying to solve?

@jayahariv Thank you for your reply.

In my case, sometimes we found a one-time push won't work properly. The changes won't push to SG Server. So I try to find a way to execute one-time push again.

We also encounter a strange problem:

The Couchbase Replicator one-time push has Unauthorized error but the continuous-pull still work properly. Any idea about this ?

👉 Pushing to mesh: status Stopped, progress 0/0 
👉 🔥 Push status Stopped, Error Code: 10401, Unauthorized
👉 Pulling  from mesh: status Busy, progress 5/5 
👉 Pulling  from mesh: status Busy, progress 6/6 
👉 Pulling  from mesh: status Idle, progress 6/6 

Can you share the configuration you are using for replicator?

Hello, basically looks like this:

// Push
let db = Database(name: "")
let config = ReplicatorConfiguration(database: db, target: replicationEndpoint)
config.authenticator = BasicAuthenticator(username: "", password: "")
config.replicatorType = .push

// Pull
let db = Database(name: "")
let config = ReplicatorConfiguration(database: db, target: replicationEndpoint)
config.authenticator = BasicAuthenticator(username: "", password: "")
config.replicatorType = .pull
config.continuous = true

Seems like you are passing in empty username and password. Can you share your sync gateway config users?

Something like below:

....
"users": {
        "GUEST": { "disabled": false, "admin_channels": ["*"] }
      }

Actually I didn't pass the empty username and password. I just comment without it. Sorry for the misleading 😂

means, you only set the replicatorType, rest all are by default(except pull, which is continuous)

Can you share the Sync Gateway config too? to see the users configured on SG config.

@jayahariv Hi, here is the SG config:

{
    "interface":":4984",
    "adminInterface":":4985",
    "logging": {
      "log_file_path": "/var/tmp/sglogs",
      "console": {
          "log_level": "debug",
          "log_keys": ["*"],
          "color_enabled": true
      },
      "error": {
          "enabled": true,
          "rotation": {
              "max_size": 100,
              "max_age": 360,
              "localtime": false
          }
      },
      "warn": {
          "enabled": true,
          "rotation": {
              "max_size": 100,
              "max_age": 180,
              "localtime": false
          }
      },
      "info": {
          "enabled": true,
          "rotation": {
              "max_size": 100,
              "max_age": 6,
              "localtime": false
          }
      },
      "debug": {
          "enabled": false,
          "rotation": {
              "max_size": 100,
              "max_age": 2,
              "localtime": false
          }
      }
    },
    "databases": {
      "foo": {
        "server": "http://couchbase-server:8091",
        "bucket": "foo",
        "username": "***",
        "password": "***",
        "users": {
          "GUEST": {"disabled": true}
        },
        "enable_shared_bucket_access": true,
        "import_docs": true,
        "allow_conflicts": false,
        "use_views": false,
        "num_index_replicas": 0,
        "bucket_op_timeout_ms": 5000,
        "sync": `
        ......
        `
      }
    }
  }

Are you configuring new users via Admin REST API?

Could you please try hard coding a user in the users list and try to replicate via the same user? Below is an example user credential john: pass

  "databases": {
    "mydatabase": {
      "users": { 
        "GUEST": {"disabled": true},
        "john": {"password": "pass"}
      }
    }
  }
}

https://docs.couchbase.com/sync-gateway/2.7/users-and-roles.html