所以我最近嘗試創建一個預訂網站,您可以在其中選擇要預訂的日期。然后您將向 /api/v1/reserve 發送一個請求,該請求將檢查資料是否有效。生成條帶支付意圖,將預訂保存到資料庫并將支付意圖id發送到前端(用于確認)。我的問題是,如果兩個客戶同時點擊發送,他們都在同一日期付款,這是不應該發生的。
router.post("/reservation", async (req, res) => {
//Check if everything is in the reqest
if (!req.body?.name || !req.body?.phone || !req.body?.date) return res.sendStatus(400);
if (!req.body.phone.match(/^[ ]{0,1}[4]{1,2}[8][\s0-9]*$/)) return res.status(400).json({
type: ErrorTypes.PHONE
});
//Validating date
const reservationDate = new Date(req.body.date);
if (reservationDate < new Date()) return res.status(400).json({
type: ErrorTypes.DATE
});
//Checking if date is already reserved
if (await checkIfDateReserved(reservationDate)) return res.status(400).json({
type: ErrorTypes.RESERVED
})
//if reservation date is weekend raise the price ??
const estimatedPrice = reservationDate.getDay() == 6 || reservationDate.getDay() == 0 ? 3500 : 2000;
try {
//Create payment intet
const intent = await stripe.paymentIntents.create({
amount: estimatedPrice,
currency: "PLN",
payment_method_types: ['card']
});
const document = new ReservationModel({
name: req.body.name,
reservationDate: reservationDate,
phone: req.body.phone,
complete: false,
intentId: intent.id
});
await document.save();
//If everything went smoothley, send the secret to the client
//Send the client the intent secret to confirm the payment
res.json({ clientSecret: intent.client_secret });
} catch (error) {
res.status(500);
}
});
基本上,兩個行程在不同的執行緒中并行運行,它們檢查日期是否同時保留并同時保留。我怎樣才能讓資料庫等到第一個保存請求完成后再處理另一個?reservationDate 欄位是唯一的,但似乎 MongoDB 仍然忽略它。
PS:另外,我考慮過使用事務,但我真的不知道它們在這里如何應用。
uj5u.com熱心網友回復:
所以由于0x1C1B,我最終在這個問題中使用了答案。互斥體最終完美地作業。如果有人需要,請留下代碼。
const mutex = new Mutex();
router.post("/reservation", async (req, res) => {
//Check if everything is in the reqest
if (!req.body?.name || !req.body?.phone || !req.body?.date) return res.sendStatus(400);
if (!req.body.phone.match(/^[\s0-9]{9,11}/)) return res.status(400).json({
type: ErrorTypes.PHONE
});
//Validating date
const reservationDate = new Date(req.body.date);
if (reservationDate < new Date()) return res.status(400).json({
type: ErrorTypes.DATE
});
await mutex.lock(); //Lock the mutex to avoid processing two reservations at once
//Checking if date is already reserved
if (await checkIfDateReserved(reservationDate)) {
mutex.release(); //Release the mutex so other requests can continue
return res.status(400).json({
type: ErrorTypes.RESERVED
})
}
//if reservation date is weekend raise the price ??
const estimatedPrice = reservationDate.getDay() == 6 || reservationDate.getDay() == 0 ? 3500 : 2000;
try {
//Create payment intet
const intent = await stripe.paymentIntents.create({
amount: estimatedPrice,
currency: "PLN",
payment_method_types: ['card']
});
const document = new ReservationModel({
name: req.body.name,
reservationDate: reservationDate,
phone: req.body.phone,
complete: false,
intentId: intent.id
});
await document.save();
//If everything went smoothley, send the secret to the client
//Send the client the intent secret to confirm the payment
res.json({ clientSecret: intent.client_secret }); //Send the client_secret required for payment confirmation
//If the confirmation doesn't go through in 5 minutes the reservation is canceled due to "createdAt" field in the schema (see ../../schemas/Reservation.ts)
//If the payment goes through the automatic deletion is cancelled (see index.ts:59)
mutex.release(); //Release mutex after reservation has been saved to db
//So other users can't reserve it
} catch (error) {
res.status(500);
mutex.release();
}
});
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/444657.html
