对并发API请求的数据库访问

时间:2019-06-04 02:46:23

标签: javascript node.js rest mongoose

如何确保数据库调用与并发API调用异步?

例如,我有一个代表游泳池的模型。

{
    limit: number e.g 5
    isOpen: boolean // will close when users.length == limit
    users: []
}

我希望在任何给定时间,数据库中只有1个非全池。 因此,我可以在API调用上运行类似的内容。

let openPool = model.findOne({isOpen: true});
if(!openPool){

    //create a new pool
    model.insert({
        limit: 5,
        users: [currentuser]
        isFull: false
    });
}else{

    //add the current user to existing open pool
    model.update({
        users: {$push: {currentuser}}
    });

    //close pool if full
    if(model.users.length == model.users.limit){
        model.update({
            isOpen: {$set: false}
        });
    }

}

当我同时向此端点发送10个请求时,每个人都认为它们是第一个,然后创建一个新池。 因此,我最终得到了新的10个池,在其中我希望有2个完整(封闭)池,每个池有5个用户。

有没有办法确保所有这些请求都按顺序执行?

也许顺序地是个坏主意。但是总的来说,我正在寻找一种方法来保持数据库状态始终有效。

Nodejs对此有用吗?

任何指向正确方向的指针将不胜感激。

1 个答案:

答案 0 :(得分:0)

解决方案是使用互斥锁来同步关键块。
我使用了async-lock

var AsyncLock = require('async-lock');
var lock = new AsyncLock();

requestHandler(){
    return new Promise(async (resolve,reject) => {
        lock.acquire('key', async () => {
           let openPool = await model.findOne({isOpen: true});
           if(!openPool){

           //create a new pool
           await model.insert({
               limit: 5,
               users: [currentuser]
               isFull: false
           });
        }else{
            //add the current user to existing open pool
            await model.update({
                users: {$push: {currentuser}}
            });

            //close pool if full
            if(model.users.length == model.users.limit){
                model.update({
                    isOpen: {$set: false}
                });
            }
        }

        return resolve(true);
    }).then(() => {
        //lock released
    });
}