在NodeJS中处理“原子性”

时间:2018-12-09 15:37:07

标签: node.js variables concurrency

我正在使用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 :(得分:0)

如果我说对了,您只是想让选票过期并在一段时间后被销毁?

如果使用猫鼬,则只需添加一个“ expires”字段,这样就不需要更多代码了。

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

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