Столкнулся с проблемой при работе обновлении записей в БД postgresql

у меня есть два таблицы(products, baskets) в этом примере у меня есть массив id товаров, которые находятся в корзине, например [1,1,1,2,3], т.е. тут есть 3 одинаковых товара но при удалении этой корзины, нужно увеличить количество товаров на 1, если у нас в этом примере 3 одинаковых товара, то в таблице products товар с id===1 нужно увеличить его свойство count на 1 если товар в корзине встречается только один раз, но у нас их 3 и след нужно увеличить значение count на 3. так вот, при написании вот этого кода, у меня увеличивает значение не на 3 как нужно, а только на 1

await Promise.all(
    products_array.map(async id => {
        let product = await ProductModel.findOne({ where: {id}}) 
        // находим продукт по id
        let updatedProduct = await ProductModel.update({count: product.count+1}, {where: {id}})
        // обновляем count продукта на 1
        return updatedProduct
    })
)

но при таком написании, все работает как и задумано

await Promise.all(
    products_array.map(async id => {
        return ProductModel.increment('count', { where: { id }}); 
    })
)

так вот, как обновить свойство продукта первым способом и почему оно не работает, можете разъяснить в чем моя ошибка.


Ответы (1 шт):

Автор решения: nörbörnën

Вы параллельно пытаетесь обновить одну и ту же запись БД и результат выполнения что первого, что второго "написания" зависит от случайных факторов. Ваш код, это - пример состояния гонки.

Лучшим решением будет заранее посчитать размер увеличения счётчика и выполнить (параллельно) редактирование записей с уникальными идентификаторами.

const products_array = [1,1,1,2,3];

const reducedProductsArray = products_array.reduce(
  (acc, x) => {
    acc[x] = (acc[x] || 0) + 1;
    return acc;
  },
  {},
);

await Promise.all(
  Object.entries(reducedProductsArray).map(
    ([id, val]) => ProductModel.increment({ count: val }, { where: { id }})
  )
);

Пример вызова метода increment я взял тут, сам не пользуюсь sequelize, так что не могу проверить корректность.

→ Ссылка