How to handle lost network connection to sync gateway?

Hello, I’m new to the couchbase world and try to write my first mobile app with a couchbase database. Therefore I have set up a Couchbase Server, the Sync Gateway and a local database in the app. The synchronization between app and server is working with replications without problems. But how do I handle the case that the app looses the network connection? If I start the app without connection to the Sync Gateway, I get many HttpHostConnectException errors. So my question is: How do I handle the case of a lost network connection properly?

The Couchbase Lite SDKs use reachability APIs on their respective platforms and retry strategies to monitor network availibility.

Those errors won’t crash your app and when they do appear, Couchbase Lite will try again at certain time intervals to replicate the data. For those reasons, I’d say it’s ok to ignore them.

James

There shouldn’t be any errors visible to your app — Couchbase Lite handles transient networking errors like these by itself.

Could you describe what platform you’re running on, what version of Couchbase Lite, and the exact form in which the errors appear?

Thank you two for your thoughts!
The app runs on an emulator with Android 5.1, API level 22, x86. I use Couchbase Lite 1.1.0. The error log says:

3625-3675/com.example.app E/RemoteRequest﹕ io exception.  url: http://192.168.5.100:4984/database/_session
    org.apache.http.conn.HttpHostConnectException: Connection to http://192.168.5.100:4984 refused
            at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:188)
            at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:169)
            at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:124)
            at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:365)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:560)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:492)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:470)
            at com.couchbase.lite.support.RemoteRequest.executeRequest(RemoteRequest.java:184)
            at com.couchbase.lite.support.RemoteRequest.run(RemoteRequest.java:103)
            at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
            at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
            at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)
     Caused by: java.net.ConnectException: failed to connect to /192.168.5.100 (port 4984) after 60000ms: isConnected failed: ECONNREFUSED (Connection refused)
            at libcore.io.IoBridge.isConnected(IoBridge.java:238)
            at libcore.io.IoBridge.connectErrno(IoBridge.java:171)
            at libcore.io.IoBridge.connect(IoBridge.java:122)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:183)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:456)
            at java.net.Socket.connect(Socket.java:882)
            at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:124)
            at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:149)
            at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:169)
            at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:124)
            at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:365)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:560)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:492)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:470)
            at com.couchbase.lite.support.RemoteRequest.executeRequest(RemoteRequest.java:184)
            at com.couchbase.lite.support.RemoteRequest.run(RemoteRequest.java:103)
            at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
            at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
            at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)
     Caused by: android.system.ErrnoException: isConnected failed: ECONNREFUSED (Connection refused)
            at libcore.io.IoBridge.isConnected(IoBridge.java:223)
            at libcore.io.IoBridge.connectErrno(IoBridge.java:171)
            at libcore.io.IoBridge.connect(IoBridge.java:122)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:183)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:456)
            at java.net.Socket.connect(Socket.java:882)
            at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:124)
            at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:149)
            at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:169)
            at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:124)
            at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:365)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:560)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:492)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:470)
            at com.couchbase.lite.support.RemoteRequest.executeRequest(RemoteRequest.java:184)
            at com.couchbase.lite.support.RemoteRequest.run(RemoteRequest.java:103)
            at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
            at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
            at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)

Does this help you, or are further information needed?

In the emulator you will see these since there is a logger. If you were to capture the error, try: Catch output to debug or something, then you could decide what to do with the message. Otherwise it’s informational. What is happening at the UI level, crash or just nothing noticeable?

At UI level nothing noticeable is happening, so for productive use it would be possible to ignore it. I was just wondering that these errors occur at all and are not handled in some way by Couchbase Lite…

Hi @Chessmaster,

CBL Android treats IOException as transient error. So CBL retries to retrieve data from sync gateway till retry counter reaches maximum. Then replicator stops. Application could get error notification through ChangeListener. (see: http://developer.couchbase.com/documentation/mobile/1.1.0/develop/references/couchbase-lite/couchbase-lite/replication/replication/index.html#void-addchangelistenerchangedelegate-delegate)

Also, as @jamiltz wrote, CBL Android observes network connectivity. Once CBL detects connection lost, replicator pauses replication, and replicator resumes once network connection is back.

If CBL Android behaves unexpectedly, please let us know.

Cheers!
Hideki

If it’s handling the exception, it shouldn’t be dumping the backtrace.

    } catch (IOException e) {
        Log.e(Log.TAG_REMOTE_REQUEST, "io exception.  url: %s", e, url);

Currently IOException is logged as Error with stack trace. Third parameter makes log function to write stacktrace.

I will review log messages for error cases.

Hi @hideki
Now, I am working on P2P replication. I want to catch this exception and let CBL Android to sync data with another database instance in P2P network. I have tried ChangeListener, according to the documentation, this delegate will be called whenever the Replication status changes and if the remote database is offline, the status should be OFFLINE, however I never get this status, only ACTIVE and STOPPED. Could you help me with this?

OFFLINE is informed in case network connectivity issue occurs. If remote endpoint is not accessible, error could be informed with STOPPED.

Hi @hideki

What is the maximum retry counter?

What happens after that and how resume is done ?

Regards
Pankaj Sharma

@pankaj.sharma,

With the latest implementation (v1.4.0), a maximum number of retry is unlimited.

1 Like