MongoDB: Найти, если не существует, вставить, уязвимость - PullRequest
0 голосов
/ 06 ноября 2019

Выполнение> 10 запросов, по крайней мере, одновременно, этот код вставляет 4 одинаковые записи, но должен вставить только 1.

Пользователь может запустить только 1 активную игру. (в активном игровом поле finished = false)

console.log('performing request');
const activeGame = await db.Game.findOne({ uid, finished: false });
if (activeGame !== null) {
    console.log('errored');
    return { error: 'Finish previous game.' };
} else {
    console.log('inserted');
    const game = new db.Game({
        uid,
        moves: new Array(5*5).fill(0)
    });
    game.save();
    return game;
}

Журналы при 10 запросах одновременно:

performing request
inserted
performing request
performing request
inserted
performing request
inserted
inserted
performing request
errored
performing request
errored
performing request
errored
performing request
errored
performing request
performing request
errored
errored

PS Транзакции мне не помогают

Ответы [ 2 ]

0 голосов
/ 06 ноября 2019

Ваш UID отличается, поэтому он будет вставлять эти времена. Если вы передадите тот же uid, он будет работать в соответствии с вами.

Вы можете попробовать это. и прочитайте функцию сохранения ().

console.log('performing request');
const activeGame = await db.Game.findOne({ _id: uid, finished: false });
if (activeGame == null) {
      console.log('inserted');
    const game = new db.Game({
        moves: new Array(5*5).fill(0)
    });
    game.save();
    return game;
} else {
    console.log('errored');
    return { error: 'Finish previous game.' };
}

ИЛИ

console.log('performing request');
const activeGame = await db.Game.findOne({ _id: uid, finished: false });
activeGame.save()
0 голосов
/ 06 ноября 2019

Конечно, этот код подвержен условиям гонки. Чтобы избежать этого, вы можете использовать Все, что вам нужно, это частичный уникальный индекс . Примените его к полю uid для документов, где finished: false и вуаля, теперь вы не можете вставить две активные игры для одного и того же пользователя.

...