Node.js:如何防止同时调用异步函数

时间:2019-01-30 21:12:54

标签: javascript node.js concurrency google-cloud-pubsub

我有一个pub子订阅服务器,该订阅服务器调用异步函数来更新一些弹性搜索索引,但是由于该订阅服务器很快收到多个请求,因此我收到来自elasticsearch的版本冲突。

我尝试添加一个处理标志,并每隔一段时间检查一次标志,以使该功能一次只能运行一个。

let unitsBeingProcessed = {};
let maxAttempts = 5;

Pubsub.on("unit_upsert", async(message) => {
try {
    let unitId = message.data.unitId;
    console.log(unitId + ' being processed is', unitsBeingProcessed[unitId]);

    // seems like sometimes 2 requests end up in this block at the same time which shouldn't be possible I think..
    if(!unitsBeingProcessed[unitId]){
        unitsBeingProcessed[unitId] = true;
        await elastic.addUnitToCalendar(message.data);
        delete unitsBeingProcessed[unitId];
        message.ack();
    }
    else if(unitsBeingProcessed[unitId]){
        let attempts = maxAttempts;
        // if unit is being processed already, check every 2 seconds to see if it's done yet
        let flagCheck = setInterval(async () => {
            attempts--;
            if(!unitsBeingProcessed[unitId]){
                clearInterval(flagCheck);
                unitsBeingProcessed[unitId] = true;
                await elastic.addUnitToCalendar(message.data);
                delete unitsBeingProcessed[unitId];
                message.ack();
            }
            else {
                if(attempts <= 0){
                    clearInterval(flagCheck);
                    throw new Error('max tries to process unit exceeded');
                }
                console.log(unitId + ' is already being processed. Waiting 2s');
            }
        }, 2000);
    }
} catch(err){
    if(unitsBeingProcessed[message.data.unitId]){
        delete unitsBeingProcessed[message.data.unitId];
    }
    Logger.error({err}, "Error in unit_availability_upsert_index");
}
})

我希望elastic.addUnitToCalendar()如果已经被调用并且尚未完成,则不会运行。在大多数情况下,间隔检查会起作用,但偶尔它仍会在完成之前调用该函数。

我的日志显示unitBeingProcessed [unitId]连续两次未定义。我希望它打印一次未定义,然后第二次打印为真,因此它将等待。关于我在做什么错的任何想法吗?

1 个答案:

答案 0 :(得分:1)

这是一个常见的多线程问题。通常,您会使用一种称为Mutex的东西。互斥锁就像一把锁,可以确保在给定的时间只有一个人可以拥有该锁。默认情况下,node.js中没有一个,但是看起来有些人已经写了https://www.npmjs.com/package/async-mutex。尝试尝试使用间隔标志,而不是使用间隔标志,这样可以使事情变得更轻松并解决您的问题。