【问题标题】:How can I handle concurrency in Node.js如何在 Node.js 中处理并发
【发布时间】:2020-10-07 08:45:30
【问题描述】:

我使用 Angular 作为前端,使用 Node.js 作为后端,同时使用 knex.js SQL builder 和 PostgreSQL。 我正在构建用户可以在其中进行约会的 Web 应用程序。 如果用户#1 进行了某个约会,例如在 10:00,则用户#2 不能进行相同的约会。

我使用setInterval() 每三秒获取一次可用的小时预约,但问题是如果用户#1 在 10:00 预约,同时用户#2 在 10 点预约: 00,那么他们俩都在 10:00 有约会。三秒后,用户#2 将无法使用创建的约会,但我如何保证用户#2 不会与用户#1 同时点击“预约”按钮,直到三秒过后?

我该如何处理?

角度

 setInterval(() => {
     this.getAvailableHourAppointments();
 }, 3000);

 getAvailableHourAppointments() {
     console.log('available called');
     this.appointmentService.getAvailableAppointmentHours(this.user.id,
         this.selected_appointment_date).subscribe(availavable_appointment_hours => {
         console.log('available', availavable_appointment_hours);
         this.availavable_appointment_hours = availavable_appointment_hours;
     })
 } 

Node.js

router.get('/available/:selected_appointment_date', (req, res) => {
    appointment.getAllAppointments().then(all_appointments => {
        all_appointments = all_appointments.filter(appointment => appointment.appointment_date == req.params.selected_appointment_date);
        const appointment_hours = appointment.getAppointmentHours();
        let availavable_appointment_hours = appointment_hours.filter(a => !all_appointments.some(b => a.value === b.appointment_hour));
        res.json(availavable_appointment_hours)
    })
})

Knex.js

function getAllAppointments() {
  return db.select('*').from('appointment');
}

编辑我用 MUTEX 尝试过的内容

router.post("make-appointment", (req, res) => {
    let user = req.body;
    user['id'] = helpers.generateUuid();
    appointment.sendMail(user, info => {
        // console.log(`The mail has beed send ???? and the id is ${info.messageId}`);
        // res.send(info);
        res.send([user]);

        appointment.postAppointment(user).then(app => {
            console.log(app);
            let locks = new Map();
            // console.log(user.id);
            if (!locks.has(user.id)) {
                console.log(1111);
                locks.set(user.id, new Mutex());
            }
            locks
                .get(user['id'])
                .acquire()
                .then(async (release) => {
                    try {
                        const existAppoinment = await appointment.getAppointmentById(app.appId).then(x => {
                            console.log(x);
                            if (x.length == 0) {
                                appointment.postAppointment(req.body).then(data => {
                                    res.json(data);
                                }).catch(err => res.json(err));
                            }
                        }).catch(err => {
                            console.log(err);
                        })
                    } catch (error) {
                        console.log(errror);
                    } finally {
                        console.log('FINALLY CALED')
                        release();
                    }
                },
                );
        })
    }, err => {
        // console.log('err', err);
    });
});

【问题讨论】:

    标签: node.js angular concurrency knex.js mutual-exclusion


    【解决方案1】:

    这是您必须在后端(Node.js 应用程序)中处理的互斥问题。 Node 中有一些包,例如 Mutex,它实现了用于在 JavaScript 中同步异步操作的原语。 所以你必须“在 NodeJS 中使用 Mutex 处理互斥”,这是一篇对你有帮助的文章:Handle Race Conditions In NodeJS Using Mutex

    以下是使用 mutex 创建 lock 的示例:

    import { Mutex, MutexInterface } from 'async-mutex';
    
    class PaymentService {
        private locks : Map<string, MutexInterface>;
    
        constructor() {
            this.locks = new Map();
        }
    
        public async participateInFreeEvent(user: User, eventId: number): Promise<void> {
            if (!this.locks.has(user.id)) {
              this.locks.set(user.id, new Mutex());
            }
            
            this.locks
                .get(user.id)
                .acquire()
                .then(async (release) => {
                    try {
                        const existOrder = await findOrder(eventId, user.id);
                        if (!existOrder) {
                            const order = buildNewOrder(eventId, user.id);
                            createOrder(order.id, eventId, user.id);
                        }
                    } catch (error) {
                    } finally {
                        release();
                    }
                },
            );
        }
    }
    

    【讨论】:

    • 你好 ng-hobby。首先非常感谢您的回复。我编辑了我的问题,这样你就可以看到我尝试了什么。但它不起作用,再次两个用户可以预约。我的错误在哪里?我在控制台中没有错误。 wkrflow如下:我预约之后,我从那个约会和用户ID中获取了ID,然后我将其余部分与锁一起使用。您能否在locks.get(user ['id)之后向我解释一下代码']) 部分
    • 您好 anderj.boshkoski1,不客气。我认为getAppointmentById() 无法正常工作。删除then(),因为您使用的是await,然后在existAppointment 中得到结果。另外将if(x.lenght ==0)替换为if(!existAppoinment )
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-23
    • 2017-12-28
    • 1970-01-01
    • 1970-01-01
    • 2018-11-22
    • 2019-03-02
    相关资源
    最近更新 更多