如何处理Node.js中的并发性

问题描述

我将 Angular 用作前端,将 Node.js 用作后端,同时使用 knex.js sql构建器和 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",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应用)中处理。 Node中有一些软件包,例如Mutex,它实现了用于同步JavaScript中异步操作的原语。 因此,您必须“使用互斥量在NodeJS中处理互斥” ,这是对您有帮助的文章:Handle Race Conditions In NodeJS Using Mutex

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

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();
                }
            },);
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...