Search code examples
node.jsmongodbtypescriptreplicaset

Node.js native mongodb losing connection with replica set when primary goes down


I have a system which uses the native node.js mongodb package (changing to something like mongoose would be a last resort due to legacy code) the current system uses a standalone mongo instance but I want to move to using a replica set. In order to test this out I have a local (Win 7) mongo instance running as primary, plus a secondary and an arbiter running on a remote (i.e. physically remote) machine on a raspberry pi (using arch linux 64-bit).

The problems is that when I shutdown the mongod process which is currently set as the primary instead of the driver reconnecting to the new primary it fails with an ECONNRESET error.

The replica set seems to be functioning correctly other than this, all nodes are "up" and in their correct states and adjust accordingly when a node is taken down.

I started off with v2.2.31 of the node.js mongodb package, and most recently tested using v3.0.4 with no change.

Initially I had mongodb v3.4.3 locally and 3.4.9 remote, so in case it was a version mismatch problem (which seemed unlikely) I set it up to use v3.6.2 at both ends but the same problem persists.

Is this a configuration issue or just a misunderstanding of how automatic the fail-over process is. Any help much appreciated.

Sample Output:

$ node compiled/replset.js
-> joined secondary

===[ item 1 of 90 ]=========================================================
'ASC3498349'
===[ item 2 of 90 ]=========================================================
'YHD9848935'
===[ item 3 of 90 ]=========================================================
'PLS3098423'
===[ item 4 of 90 ]=========================================================
'JDJ2340982'
===[ item 5 of 90 ]=========================================================
'MDK3489346'
===[ item 6 of 90 ]=========================================================
'LDE3948849'
-> all servers connected

-> left primary

{ Error: read ECONNRESET
    at _errnoException (util.js:1024:11)
    at TCP.onread (net.js:615:25)
  name: 'MongoNetworkError',
  message: 'read ECONNRESET',
  stack: 'Error: read ECONNRESET\n    at _errnoException (util.js:1024:11)\n at TCP.onread (net.js:615:25)' }

Test Program:

import * as util from "util";
import * as mongodb from 'mongodb';

const { ReplSet } = require('mongodb-topology-manager');

process.on('unhandledRejection', (err) => {
    console.log(err);
    process.exit();
});

(async () => {

    const client = await mongodb.MongoClient.connect('mongodb://user:pass@<HOST1>:<PORT1>,<HOST2>:<PORT2>,<HOST3>:<PORT3>/test?replicaSet=rs&authMechanism=DEFAULT&authSource=admin');

    client.topology.on('left', (data: any) => {
        console.log('-> left', data);
        console.log(``);
    });
    client.topology.on('joined', (data: any) => {
        console.log('-> joined', data);
        console.log(``);
    });
    client.on('fullsetup', () => {
        console.log('-> all servers connected');
        console.log(``);
    });

    const totalCount = 90
    let count = 1;
    const INTERVAL = 1000;
    const db = client.db('test');
    const col = db.collection('items');
    const timer = setTimeout(onTimer, INTERVAL);

    async function onTimer() {

        const item = await col.findOne({}, {
            skip: count,
        });
        console.log(`===[ item ${count} of ${totalCount} ]===========================================================================`);
        console.log(util.inspect(item, { colors: true, depth: null }));
        count++;

        if (count > totalCount) {
            client.close();
            console.log('done');
        }
        else {
            setTimeout(onTimer, INTERVAL);
        }
    }
})();

Solution

  • Sorry, probably just not seeing the wood for the trees! Just handling the ECONNRESET exception thrown from the find and continuing and all is good.