Replica set doesn't make election if insertion interval is less than 501 ms

  • I’m Using Mongodb Native driver 3.6

  • configured PSA replicaSet (on the same machine) and this is its configuration parameters

rs0:PRIMARY> rs.config()
{
        "_id" : "rs0",
        "version" : 319263,
        "protocolVersion" : NumberLong(1),
        "writeConcernMajorityJournalDefault" : true,
        "members" : [
                {
                        "_id" : 2,
                        "host" : "192.168.45.77:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 5,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 4,
                        "host" : "192.168.45.77:27015",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 5,
                        "host" : "192.168.45.77:27020",
                        "arbiterOnly" : true,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 0,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                }
        ],
        "settings" : {
                "chainingAllowed" : true,
                "heartbeatIntervalMillis" : 2000,
                "heartbeatTimeoutSecs" : 10,
                "electionTimeoutMillis" : 5000,
                "catchUpTimeoutMillis" : -1,
                "catchUpTakeoverDelayMillis" : 30000,
                "getLastErrorModes" : {

                },
                "getLastErrorDefaults" : {
                        "w" : 1,
                        "wtimeout" : 0
                },
                "replicaSetId" : ObjectId("5ed8d7489ff195f6b8ff442c")
        }
}

i tried to insert into the database with interval and intentionaly stop the primary server to confirm election is done and a new primary is selected

const {ObjectID, MongoClient } = require('mongodb')

client = new MongoClient('mongodb://localhost:27017,localhost:27015,localhost:27020/logs?replicaSet=rs0', {
  useUnifiedTopology: true,
  serverSelectionTimeoutMS: 15000
})

client.on('topologyDescriptionChanged', event => {
  console.log(event.newDescription.type)
})

let db

client.connect((err, client) => {
  if (err) {
    return console.log('error inside connection', err)
  } 
  
  db = client
})

setInterval(() => {
  db
    .db()
    .collection('logs')
    .insertOne({
      _id: new ObjectID(),
      foo: 'bar'
    })
    .then(result => {
      console.log(result.insertedId)
    })
    .catch(err => {
      console.log(`err`, err)
    })
}, 500)
  • There are two scenarios

1- interval time is more than 500 ms

  • topologyDescriptionChanged event is fired more than one time
  • in this case election is made normally and everything is ok

2- interval time is less than 501 ms

  • topologyDescriptionChanged event is fired once with type ReplicaSetNoPrimary and after it reaches serverSelectionTimeoutMS it throws MongoServerSelectionError: not master which means no election is made

any help please?

  • Also i tried in python with pymongo
from pymongo import MongoClient
from time import sleep


import threading

def set_interval(func, sec):
    def func_wrapper():
        set_interval(func, sec)
        func()
    t = threading.Timer(sec, func_wrapper)
    t.start()
    return t


c = MongoClient('mongodb://localhost:27017,localhost:27015,localhost:27020/?replicaSet=rs0').test

def insert():
    z = c.test.insert_one({"x": 1})
    print(z.inserted_id)


set_interval(insert,.1)

in interval 100 ms it worked fine and no errors