我有一个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]连续两次未定义。我希望它打印一次未定义,然后第二次打印为真,因此它将等待。关于我在做什么错的任何想法吗?
答案 0 :(得分:1)
这是一个常见的多线程问题。通常,您会使用一种称为Mutex的东西。互斥锁就像一把锁,可以确保在给定的时间只有一个人可以拥有该锁。默认情况下,node.js中没有一个,但是看起来有些人已经写了https://www.npmjs.com/package/async-mutex。尝试尝试使用间隔标志,而不是使用间隔标志,这样可以使事情变得更轻松并解决您的问题。