我的Node.js应用程序中有一个循环,它不断从我的数据库中获取“未处理”的行(每秒1个请求)。
我从数据库收到的每一行都会调用一个具有唯一数字ID的函数,以及来自数据库的其他详细信息作为参数。只要在此函数内处理数据,就会更新数据库,并将该行标记为“已处理”。
function fetch() {
db.query("SELECT id, data FROM table WHERE processed=0 ORDER BY id ASC", function(err, results) {
if(results.length > 0) {
for(var i=0; i<results.length; i++)
process(results[i].id, results[i].data);
}
});
}
var interval_fetch = setInterval(fetch, 1000);
function process(id, data) {
// Process data
db.query("UPDATE table SET processed=1 WHERE id="+id);
}
但是,在某些情况下,数据和更新数据库需要一秒钟以上的处理时间。在这种情况下,process()使用相同的参数调用两次甚至更多次。
Node.js环境中最简单的方法是确保只使用某个ID参数同时调用该函数一次?
是否有任何软件包提供此功能并且只需要两到三行额外代码?
(解决方案不一定要防止多次调用该函数。如果我能够检查内部进程(),如果已经使用某个id调用它,我可以在数据之前结束它处理两次。)
答案 0 :(得分:0)
是否有任何软件包提供此功能并且只需要两到三行额外代码?
是:https://github.com/isaacs/once
此外,所有承诺库都应提供开箱即用的功能。和发电机。
但我建议改变你的编码方式,而不是使用它们。 setTimeout而不是setInterval可以通过这种方式消除整个问题:
function fetch() {
db.query("SELECT id, data FROM table WHERE processed=0 ORDER BY id ASC", function(err, results) {
if(results.length > 0) {
for(var i=0; i<results.length; i++)
process(results[i].id, results[i].data)
}
setTimeout(fetch, 1000)
})
}
var interval_fetch = setTimeout(fetch, 1000)
function process(id, data) {
// Process data
db.query("UPDATE table SET processed=1 WHERE id="+id)
}
答案 1 :(得分:0)
简化,在作业完成后设置超时。
function fetch() {
db.query("SELECT id, data FROM table WHERE processed=0 ORDER BY id ASC", function(err, results) {
if(results.length > 0) {
for(var i=0; i<results.length; i++)
process(results[i].id, results[i].data);
}
});
}
setTimeout(fetch, 1000);
function process(id, data) {
// Process data
db.query("UPDATE table SET processed=1 WHERE id="+id, function() {
setTimeout(fetch, 1000);
});
}
答案 2 :(得分:0)
今天早上我得到了一个相对简单的解决方案。因此,我正在回答我自己的问题。
我只是维护一个对象,其中包含当前已处理但尚未在DB中更新的所有ID。每次调用process()时,我都会检查ID当前是否正在进行,如果适用则取消,然后再处理两次数据。
var in_progress = {}; // Object that contains the IDs
function fetch() {
db.query("SELECT id, data FROM table WHERE processed=0 ORDER BY id ASC", function(err, results) {
if(results.length > 0) {
for(var i=0; i<results.length; i++)
process(results[i].id, results[i].data);
}
});
}
var interval_fetch = setInterval(fetch, 1000);
function process(id, data) {
if(in_progress.hasOwnProperty(id)) { // Check if ID is in progress
console.log("ID "+id+" in progress - do nothing");
return;
} else {
in_progress[id] = true; // Insert ID into object
// Process data here, then run below query
db.query("UPDATE table SET processed=1 WHERE id="+id, function() {
// Remove ID from object once DB is updated - Timeout to make sure nothing can overlap with the fetch function
setTimeout(function(){ delete in_progress[id]; }, 1000);
});
}
}
这完全符合我的要求。我甚至可以制作更快的获取间隔,开始处理来自我的数据库的所有新数据,而没有明显的延迟。仍然没有任何东西会被处理两次。