Как обработать запрос на обновление от разных пользователей в одной коллекции продуктов для одного и того же идентификатора продукта в одно и то же время mongodb - PullRequest
0 голосов
/ 22 сентября 2019

У меня есть коллекция продуктов.И я хочу обработать случай, когда 8 пользователей оформляют заказ на один и тот же продукт одновременно.И предположим, что запрос всех 8 пользователей прошел внутри части обновления, тогда в какой момент пользователь получит продукт, а как насчет запроса на обновление остальных 7 пользователей?

8 пользователь внутри той же функции обновления, один пользователь получит обновление и количество доступных продуктов0, если товара нет в наличии отправленная ошибка или откат базы данных

1 Ответ

0 голосов
/ 22 сентября 2019

Вы можете реализовать механизм «блокировки», позволяющий одновременно выполнять только одну транзакцию с данным продуктом.

Может быть, что-то вроде этого.(Я не тестировал этот код; просто набросал идею.)

// utility function that just waits the specified duration and resolves
const sleep = duration => new Promise(resolve => setTimeout(resolve, duration));

// a map of the currently active locks
const locks = {};

// productId: the key to lock on
// transaction: an async function that performs the transaction
// timeout: how long to keep retrying before throwing
async function withLock (productId, transaction, timeout) {

  // if there's already a lock on this id...
  if (locks[productId]) {

    // …and we've exhausted the timeout…
    if (timeout <= 0) {
      // …throw an error
      throw new Error('Unable to acquire lock');
    }

    // otherwise wait 100ms…
    await sleep(100);

    // …and try again, reducing the timeout
    return withLock(productId, transaction, timeout - 100);
  }

  // no existing lock on this productId; proceed.
  try {
    // establish the lock so other calls on this id have to wait
    locks[productId] = true;

    // perform the transaction
    return await transaction();
  }
  finally {
    // and release the lock
    delete locks[productId];
  }
}

С этим на месте вы можете сделать:

try {
  const result = await withLock(productId, async () => {
    // perform checkout, update mongo, deduct inventory, whatever
  }, 2000);
}
catch (e) {
  // something went wrong, possibly a lock timeout
}

И

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...