How to know when we've lost sync with a remote CouchDB
Asked Answered
B

4

8

I have a mobile app using PouchDB that listens for changes from a remote CouchDB server. Occasionally the app pushes it's own changes up. Is there a way to check to see if I still have an active "connection" to the remote CouchDB instance?

The best solution I can come up with so far is to periodically call db.info and see if I get an error back, but that seems slightly risky.

Batton answered 12/11, 2014 at 17:2 Comment(0)
T
7

As far as I could find out, PouchDB has no event to inform us that the syncing was stopped because of a disruption in the internet connection. I did a small hack to solve this.

When the sync is happening properly, and you make a change to your local PouchDB, the order in which events are fired is:

  1. active
  2. change
  3. paused

However, when the internet is broken, the order is:

  1. active
  2. paused

There is no change event fired when syncing with the remote DB isn't taking place.

So, what I've done is made two flags for the active and change events , pouchDbSyncActiveEvent and pouchDbSyncChangeEvent respectively, and initialized both as false. Turn pouchDbSyncActiveEvent to true in the callback for the 'active' event. This will run regardless of whether there is internet or not. Turn pouchDbSyncChangeEvent to true in the callback for the 'change' event. If there is no internet, this won't run and pouchDbSyncChangeEvent will still remain false, and the 'paused' event will be fired soon after. This informs us that the syncing was stopped.

Code:

let pouchDbSyncActiveEvent = false
let pouchDbSyncChangeEvent = false

localPouchDb.sync(remoteCouchDb, {
  live: true,
  retry: true
})
.on('active', (change) => {

  pouchDbSyncActiveEvent = true

})
.on('change', (change) => {

  pouchDbSyncChangeEvent = true

})
.on('paused', (info) => {

  if(pouchDbSyncActiveEvent == true && pouchDbSyncChangeEvent == false){

    // Gotcha! Syncing with remote DB not happening!

  }
  else {

    // Everything's ok. Syncing with remote DB happening normally.

  }

  pouchDbSyncActiveEvent = false
  pouchDbSyncChangeEvent = false

})

Note: You can write the .on event listener methods in the order you wish, but it is good to write them in the order they are executed :)

Taintless answered 17/1, 2019 at 13:51 Comment(0)
L
0

I'm assuming that you included the pouchdb tag because you're using PouchDB locally and are replicating between your local PouchDB and remote CouchDB. Assuming so, replication in PouchDB is an event emitter, so there are a bunch of different events you can define in your sync or replicate call, see the docs including the error event.

Lucindalucine answered 12/11, 2014 at 18:47 Comment(6)
You are correct that I'm using pouchCB. I forgot to mention that. The options for replicate and sync don't trigger an event when a 'connection' is lost. What happens if you lose your internet connection? You would fail to know anything happened until you tried to push a change up.. the "listening" seems to fail silently.Batton
Oh right. I see what you want now. I'm not sure if there's any way to get that. The whole idea is that you don't care whether the connection is up or down, you just use the local PouchDB and whenever the connection resumes the syncing resumes.Lucindalucine
Poop. I suppose I can go back to checking the connection on a periodic with db.info.Batton
Let me ask, why do you care when the connection goes up/down?Lucindalucine
When the 'connection' is down I need to alert the user that they will no longer be receiving updates. I also need to disable the user from being able to send updates (updates would be getting queued if the connection was down).Batton
If you're needing that sort of real-time message transfer, then this sort of data replication approach is probably not the best way to go about it. I'd use websockets instead, which give much better visibility of that connection state.Lucindalucine
P
0

Did you try to look for an error in the paused event emitted when connection is lost?

localDB.replicate.to(remoteDB, {
  live: true,
  retry: true,
}).on('paused', (err) =>{
  console.log('paused');
  if (err) {
    alert(`No connection! ${err}`);
  }
  // replication was paused, usually because of a lost connection
}).on('change', (change)=>{
  // yo, something changed!
}).on('active', (info)=>{
  // replication was resumed
}).on('error', (err)=>{
  // totally unhandled error (shouldn't happen)
});

If you are using a live replication a paused event is emitted when the replication waits for a change and err is undefined. If there is a problem like a connection interruption a paused event is also emitted but with an err argument.

Note: I'm sure that there is safer ways to check if err is defined.

From the PouchDB documentation:

paused (err) - This event fires when the replication is paused, either because a live replication is waiting for changes, or replication has temporarily failed, with err, and is attempting to resume.

Photodynamics answered 21/2, 2017 at 14:51 Comment(2)
tried - does not work. start sync, then turn remote db down - paused err is undefinedUltramicroscope
Fires paused after sync is complete also. Pouchdb 7.0,0Vilhelmina
S
0

You need to set "retry" to false, or the error event won't get caught.

From the API reference:

error (err) - This event is fired when the replication is stopped due to an unrecoverable failure. If retry is false, this will also fire when the user goes offline or another network error occurs (so you can handle retries yourself, if you want).

Try this code:

    // Sync pouch - couch
db.sync(couch, {
    live: true,
    retry: false
}).on('error', (err) => {
    console.log(`A sync error occurred: ${err}`);
});
Skiplane answered 17/2, 2018 at 17:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.