Я работаю над приложением с NodeJS, Mongodb и Mariadb.Пользователи могут создавать голоса за некоторые действия.Они действительны в течение определенного времени.Чтобы контролировать, является ли голос действительным или нет, я сохраняю их в коллекции вместе со временем их создания и начинаю тайм-аут с самого «старого» голосования, потому что срок его действия истекает первым.Поэтому, если время ожидания истекло, голос удаляется, а следующий голос (если он есть) создает время ожидания.Если не осталось голосов, ничего не происходит.Поэтому мне нужно как-то проверить, работает ли тайм-аут, поэтому мне просто нужно добавить голос в базу данных или, кроме того, мне нужно создать тайм-аут.Если быть более точным, если в базе данных нет записи, мне нужно запустить тайм-аут.Но этот поиск в mongodb небезопасен, потому что нет «транзакции».
Вот мой подход, но я думаю, что он небезопасен: у меня есть индексный файл с:
let timeoutRunning = false;
activateTimeout = ()=>{timeoutRunning=true;}
deactivateTimeout = ()=>{timeoutRunning=false;}
module.exports = [timeout, activateTimeout, deactivateTimeout]
В другом файле:
const index = require("index.js");
const Vote = require("voteModel.js");
router.post("/createVote", (req, res)=>{
//some other stuff
let v = new Vote({voteId:1, type:0, iat:Date.now()})
Vote.insertVote(v)
.then((item)=>{
console.log("adding vote ", v.voteId)
//only set Timeout if there is no running
if(!index.timeoutRunning){ // is index.timeoutRunning just a copy?
index.activateTimeout();
console.log(" creating timeout for vote ",v.voteId)
setTimeout(()=>{handleExpiredVote(v.voteId, v.type)}, 100000)
}
})
.catch((err)=>{
console.log(err)
})
})
handleExpiredVote = (voteId, type)=>{
Vote.deleteVote(voteId).exec()
.then((status)=>{
console.log(status)
console.log("Deleting Vote ", voteId)
return Vote.getNextVote().exec()
})
.then((nextVote)=>{
if(nextVote!= null){
console.log("NEXT, creating timeout for vote ",nextVote.voteId)
setTimeout(()=>{handleExpiredVote(nextVote.voteId,
nextVote.type)}, 1000)
}else{
console.log("no votes left")
index.deactivateTimeout();
}
})
.catch((err)=>{
console.log(err)
})
Я знаюNodeJS однопоточный.Но безопасна ли эта идея?Что делать, если есть доступ к переменной timeoutRunning до выполнения функции activTimeout другого вызова?
Какой лучший способ решить эту проблему?
Спасибо!