fix: invite thread safety

This commit is contained in:
zkldi
2022-08-20 00:10:01 +01:00
parent bbe4d560ab
commit 4147131b29
2 changed files with 32 additions and 6 deletions
+1
View File
@@ -156,6 +156,7 @@ const db = {
"orphan-scores": monkDB.get<OrphanScoreDocument>("orphan-scores"),
"import-locks": monkDB.get<{ userID: integer; locked: boolean }>("import-locks"),
tables: monkDB.get<TableDocument>("tables"),
"invite-locks": monkDB.get<{ userID: integer; locked: boolean }>("invite-locks"),
"game-settings": monkDB.get<UGPTSettings>("game-settings"),
"game-stats-snapshots": monkDB.get<UserGameStatsSnapshot>("game-stats-snapshots"),
"session-view-cache": monkDB.get<SessionViewDocument>("session-view-cache"),
@@ -59,8 +59,6 @@ router.get("/limit", async (req, res) => {
});
});
const InviteLocks = new Set();
/**
* Create a new invite.
*
@@ -68,19 +66,39 @@ const InviteLocks = new Set();
*/
router.post("/create", async (req, res) => {
const user = GetTachiData(req, "requestedUser");
const userID = user.id;
try {
const lockExists = await db["invite-locks"].findOne({
userID,
});
if (!lockExists) {
await db["invite-locks"].insert({
userID,
locked: false,
});
}
const isNotLocked = await db["invite-locks"].findOneAndUpdate(
{
userID,
locked: false,
},
{
$set: { locked: true },
}
);
// race condition protection
// to avoid users double-creating invites.
if (InviteLocks.has(user.id)) {
if (!isNotLocked) {
return res.status(409).json({
success: false,
description: `You already have an outgoing invite creation request.`,
});
}
InviteLocks.add(user.id);
const existingInvites = await db.invites.count({ createdBy: user.id });
if (
@@ -112,7 +130,14 @@ router.post("/create", async (req, res) => {
body: inviteDoc,
});
} finally {
InviteLocks.delete(user.id);
await db["invite-locks"].findOneAndUpdate(
{
userID,
},
{
$set: { locked: false },
}
);
}
});