Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 如果数据库关闭一段时间,MongoDB将更改流超时_Node.js_Mongodb_Changestream - Fatal编程技术网

Node.js 如果数据库关闭一段时间,MongoDB将更改流超时

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

我在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!');
});

但我无法处理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(即恢复令牌)开始监视