Работа с «атомарностью» в NodeJS - PullRequest
0 голосов
/ 09 декабря 2018

Я работаю над приложением с 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 другого вызова?

Какой лучший способ решить эту проблему?

Спасибо!

1 Ответ

0 голосов
/ 10 декабря 2018

Если я вас правильно понял, вы просто хотите, чтобы ваши голоса истекли и были уничтожены через некоторое время?

Если вы используете mongoose, вы можете просто добавить поле 'expires', поэтому больше не требуется кодот вас.

Например, если вы хотите, чтобы ваш голос был действительным только один день, вы можете сделать:

const VoteSchema = new mongoose.Schema({
  name: String,
  createdAt: { type: Date, expires: '1d' }
}); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...