这是我在之前的问题中遇到的另一个问题的后续问题:
nodejs: read from file and store to db, limit maximum concurrent db operations
问题:
我想稍后重新安排一些操作,但是这会破坏我处理背压的方法。
详情:
我有一个CSV文件,我正在以流的形式阅读,并使用转换转换为JSON,然后将每行异步存储到数据库。
当变换处理行时,它们被放置在异步队列上,该队列负责发出数据库操作。
E.g。
parser._transform = function(data, encoding, done) {
var tick = this._parseRow(data);
dbQueue.push(tick, function(err, result) {
if (typeof(err) != 'undefined') { console.log(err) }
});
this.push(tick);
done();
}
当队列饱和/空时,通过暂停和恢复解析器来处理背压:
dbQueue.saturated = function() {
parser.pause();
}
dbQueue.empty = function() {
parser.resume();
}
我一直试图做的改变是,当一个项目从队列中取出时,它将在未来有条件地重新安排一段时间(100ms):
var dbQueue = async.queue(function(data, callback) {
if (condition) {
// re-schedule operation by adding back to queue 100ms later
setTimeout(function(data, callback) {
dbQueue.push(data, function(err, result){
});
}, 100, data, callback);
} else {
//execute the db store
... ...
}
}
我认为我的问题是现在很多操作都会花费大部分时间在setTimeout中,因此dbQueue将为空,并且转换流的背压未按要求处理。
我尝试过几次尝试使用max_ops和running_ops等计数器来确保暂停/恢复流,但是没有成功。
在node.js中是否有更惯用的处理方式?
答案 0 :(得分:0)
由于这看起来像是一个外部条件,而不是与dbQueue
正在做什么相关的东西,而不是在条件发生时将数据重新插入队列,我会暂停dbQueue
。例如,假设您的条件是数据库由于某种原因而断开连接,并且您可以监听该事件。在这种情况下,您可以执行类似于dbQueue
饱和/空时您正在执行的操作:
db.on('disconnect', function() {
dbQueue.pause();
});
db.on('connect', function() {
dbQueue.resume();
});
这通常比等待一些预先确定的超时更好。话虽如此,有时等待超时是唯一的选择。在这种情况下,您可以执行类似的操作,但不要等待单独的事件触发resume()
,只需使用setTimeout()
:
db.on('disconnect', function() {
dbQueue.pause();
setTimeout(function() {
dbQueue.resume();
});
});
注意:如果我们真的在这里讨论数据库断开连接,那么如果在100ms不存在的情况下出现db错误,您可能还想暂停/恢复dbQueue
有足够的时间让数据库重新连接
如果你有一个更具体的条件,你正在寻找,并且你愿意分享它是什么,我可以给你一个更好的例子:)