Node.js 如果数据库关闭一段时间,MongoDB将更改流超时
我在nodejs中使用mongoDB变更流,一切正常,但若数据库关闭,启动变更流所花费的时间超过10-5秒,则会抛出超时错误,这是我的变更流监视程序代码Node.js 如果数据库关闭一段时间,MongoDB将更改流超时,node.js,mongodb,changestream,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
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!');
});
但我无法处理change stream watcher在数据库关闭时停止它,并在数据库重新连接或有其他更好的方法时再次启动它?您要做的是将
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\u collection()
包含watch()
方法及其处理程序。更改时,它将打印更改并存储恢复令牌。出现错误时,它将调用自身来重新观看集合。这是我开发的解决方案,只需添加stream.On(error)函数,这样当出现错误时它不会崩溃,因为在数据库重新连接时重新启动流,还可以为每个事件将resume令牌保存在文件中,当应用程序崩溃或停止,您再次运行时,这是很有用的,在此期间,如果添加了x个记录,那么在应用程序重新启动时,只需从文件中获取最后一个恢复令牌,并从那里启动watcher,它将获得插入之后的所有记录,因此不会丢失任何记录,下面是代码
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 ')
})
是的,这就是解决方案,我以同样的方式实现,它现在正在工作,而且我现在正在将恢复令牌保存在文件中,在再次运行时,它从该文件中获取,现在即使应用程序崩溃或停止,但当它再次处于活动状态时,它将从保存的最后一个成功事件id(即恢复令牌)开始监视