2014-02-14 46 views
0

调用双函数我的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参数只能调用一次?

是否有提供此功能,需要额外的代码只有两三行的任何包? (这个解决方案不一定要防止多次调用该函数,如果我能够在process()中检查,如果它已经被一个特定的ID调用,那么我可以在它之前结束它数据被处理两次。)

回答

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); 
    }); 
    } 
} 

这和我想要的完全一样。我甚至可以更快地获取间隔,开始处理来自我的数据库的所有新数据,而不会有明显的延迟。仍然没有东西会被处理两次。

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) 
} 
+0

相信'setInterval'的意图是因为他要重复作业每一秒,不是因为他只希望它发生一次。 – Nucleon

+0

这就是为什么我在那里添加递归'setTimeout'调用 –

+0

我很感谢您的回复。该包部分做我想要的,但setTimeout建议不。请看我自己的答案。 – 1nsane

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); 
    }); 

} 
+0

感谢您的回答。不幸的是,这不起作用,因为我想。如果查询返回具有不同数据的多行,则process()被称为具有不同参数的多次。每个人一旦完成就会设置一个新的超时时间。如果一个函数调用在0之后完成。1秒钟和5秒钟后,另一个缓慢的将再次处理。 – 1nsane