首页 文章

处理NodeJS中的“原子性”

提问于
浏览
0

我正在使用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是单线程的 . 但这个想法安全吗?如果在执行另一个调用的activateTimeout函数之前对timeoutRunning变量有访问权限怎么办?

什么是解决这个问题的更好方法?

谢谢!

1 回答

  • 0

    如果我找对你,你只是希望你的选票过期并在一段时间后被销毁?

    如果你使用mongoose,你可以添加一个'expires'字段,因此不再需要你的代码 .

    例如,如果您希望您的投票仅在一天内有效,您可以执行以下操作:

    const VoteSchema = new mongoose.Schema({
      name: String,
      createdAt: { type: Date, expires: '1d' }
    });
    

相关问题