gpt4 book ai didi

node.js - mongoDB 和 nodeJs 无法正确处理并发请求

转载 作者:可可西里 更新时间:2023-11-01 09:12:52 31 4
gpt4 key购买 nike

我正在开发基于 socket.io room 的项目。我将 socket 与 nodejs 结合使用,并在 mongoDB 中管理房间数据。

这是我的代码,只有两个玩家可以加入一个房间,然后在我将 IsGameOn 标志从 false 变为 true 之后。
当我一个一个地向服务器发送请求时,这段代码工作正常。
当许多请求同时出现时,就会出现问题。问题是超过 2 个玩家加入了房间(房间玩家的数据存储在玩家数组中)。

我还上传了数据库的图像。因此,您可以看到数据库中实际发生了什么。

const joinRoom = async (sData, callback) => {

if(sData.iPlayerId && sData.eRoomCount)
{
try {

let body = _.pick(sData, ['eRoomCount', 'iPlayerId']);

console.log(body);

await roomsModel.aggregate([
{
$match: {
eRoomCount: body.eRoomCount,
IsGameOn: { $eq: false }
}
},
{ $unwind: "$aPlayers" },
{
$group: {
_id: "$_id",
eRoomCount: { $first: "$eRoomCount" },
aPlayers: { $push: "$aPlayers" },
size: { $sum: 1 }
}
},
{
$match: {
size: { '$lt': body.eRoomCount }
}
},
{ $sort: { size: -1 } }
]).exec((error, data) => {
if (data.length < 1) {

let params = {
eRoomCount: body.eRoomCount,
aPlayers: [{
iPlayerId: body.iPlayerId
}]
}
let newRoom = new roomsModel(params);
console.log(JSON.stringify(newRoom));
newRoom.save().then((room) => {
console.log("succ", room);
callback(null,room);
}).catch((e) => {
callback(e,null);
});
} else {
roomsModel.findOne({ _id: data[0]._id }, (error, room) => {

if (error) {
callback(error,null);
}

if (!room) {
console.log("No room found");
callback("No room found",null);
}

room.aPlayers.push({ iPlayerId: body.iPlayerId });
if (room.aPlayers.length === room.eRoomCount) {
room.IsGameOn = true;
}

room.save().then((room) => {
callback(null,room);
}).catch((e) => {
callback(e,null);
});

})
}
});

} catch (e) {
console.log(`Error :: ${e}`);
let err = `Error :: ${e}`;
callback(e,null);
}
}
}

当请求一个接一个地出现时,就会发生这种情况。 This is happens when request comes one by one.

当同时收到许多请求时会发生这种情况。 enter image description here

最佳答案

正确的方法是使用 mongoose 的 findOneAndUpdate 而不是 findOnefindOneAndUpdate 操作是原子的。如果您执行正确的查询,您可以使您的代码线程安全。

// This makes sure, that only rooms with one or no player gets selected.
query = {
// Like before
_id: data[0]._id,
// This is a bit inelegant and can be improved (but would work fast)
$or: {
{ aPlayers: { $size: 0 } },
{ aPlayers: { $size: 1 } }
}
}

// $addToSet only adds a value to a set if it not present.
// This prevents a user playing vs. him/herself
update = { $addToSet: { aPlayers: { iPlayerId: body.iPlayerId } } }

// This returns the updated document, not the old one
options = { new: true }

// Execute the query
// You can pass in a callback function
db.rooms.findOneAndUpdate(query, update, options, callback)

关于node.js - mongoDB 和 nodeJs 无法正确处理并发请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50872836/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com