如果数据库关闭一段时间,MongoDB会更改流超时

时间:2019-02-10 08:43:34

标签: node.js mongodb changestream

我在nodejs中使用mongoDB更改流,一切正常,但是如果数据库关闭花费了10到5秒钟以上的时间来使更改流抛出超时错误,这是我的更改流观察者代码

Service.prototype.watcher = function( db ){

let collection = db.collection('tokens');
let changeStream = collection.watch({ fullDocument: 'updateLookup' });
let resumeToken, newChangeStream;

changeStream.on('change', next => {
    resumeToken = next._id;
    console.log('data is ', JSON.stringify(next))
    changeStream.close();
    // console.log('resumeToken is ', JSON.stringify(resumeToken))
    newChangeStream = collection.watch({ resumeAfter : resumeToken });
    newChangeStream.on('change', next => {
        console.log('insert called ', JSON.stringify( next ))
    });
});

但是在数据库端,我已经处理了它,也就是说,如果数据库已关闭或通过使用此代码重新连接

 this.db.on('reconnected', function () {
    console.info('MongoDB reconnected!');
});
this.db.on('disconnected', function() {
    console.warn('MongoDB disconnected!');
});

但是我无法处理变更流观察程序以在数据库关闭时将其停止,并在重新连接数据库时或者是否还有其他更好的方法来重新启动它?

2 个答案:

答案 0 :(得分:1)

您想要做的是将watch()调用封装在一个函数中。然后,此函数将在错误时自行调用,以使用先前保存的恢复令牌重新监视集合。您的代码缺少的是错误处理程序。例如:

const MongoClient = require('mongodb').MongoClient
const uri = 'mongodb://localhost:27017/test?replicaSet=replset'
var resume_token = null

run()

function watch_collection(con, db, coll) {
  console.log(new Date() + ' watching: ' + coll)
  con.db(db).collection(coll).watch({resumeAfter: resume_token})
    .on('change', data => {
      console.log(data)
      resume_token = data._id
    })
    .on('error', err => {
      console.log(new Date() + ' error: ' + err)
      watch_collection(con, coll)
    })
}

async function run() {
  con = await MongoClient.connect(uri, {"useNewUrlParser": true})
  watch_collection(con, 'test', 'test')
}

请注意,watch_collection()包含watch()方法及其处理程序。更改时,它将打印更改并存储恢复令牌。出错时,它会再次调用自己以重新监视集合。

答案 1 :(得分:0)

这是我开发的解决方案,只需添加stream.on(error)函数,这样它就不会在出现错误时崩溃,因为在重新连接数据库时重新启动流,还为每个事件将恢复令牌保存在文件中,这是当应用程序崩溃或停止并且再次运行时很有用,并且在此期间,如果添加了x条记录,那么在应用程序重新启动时,只需从文件中获取最后一个恢复令牌,然后从那里启动观察程序,它将在此之后插入所有记录,因此没有记录将丢失,这是下面的代码

var rsToken ;
    try {
        rsToken = await this.getResumetoken()
    } catch (error) {
        rsToken = null ;
    }

    if (!rsToken)
        changeStream = collection.watch({ fullDocument: 'updateLookup' });
    else 
        changeStream = collection.watch({ fullDocument: 'updateLookup', resumeAfter : rsToken  });

    changeStream.on('change', next => {

        resumeToken = next._id;
        THIS.saveTokenInfile(resumeToken)

        cs_processor.process( next )


    });  
    changeStream.on('error', err => {
        console.log('changestream error ')
    })