Моя система получает полезную нагрузку из другого источника.Эта полезная нагрузка содержит информацию об элементах, включая марку и т. Д.
Я сохраняю эту полезную нагрузку в буфере.Буферы обрабатываются асинхронно с заданиями Celery.На основе полезной нагрузки мы создаем записи или обновляем их при необходимости.Это делается с помощью атомарной транзакции, в которой мы создаем Элемент, Бренд и Категорию.
Проблема, с которой я сталкиваюсь, заключается в том, что два буфера могут иметь Бренд, которого еще нет.создано в БД.Используя update_or_create внутри атомарного блока, я проверяю, существует ли он уже.Поскольку оба буфера работают асинхронно почти в одно и то же время, оба считают, что Бренда еще не существует.Это означает, что они оба пытаются создать Бренд, выдавая мне следующую ошибку базы данных:
postgres_1 |ОШИБКА: двойное значение ключа нарушает уникальное ограничение "catalogue_brand_name_key" postgres_1 |ДЕТАЛИ: Ключ (имя) = (Bic) уже существует.postgres_1 |ЗАЯВЛЕНИЕ: INSERT INTO "catalogue_brand" ("id", "create_date", "updated_date", "name") ЗНАЧЕНИЯ ('c8e9f328-cee7-4b9b-ba45-268180c723d8' :: uuid, '2018-12-28T08: 08:51.519672 + 00: 00 ':: timestamptz,' 2018-12-28T08: 08: 51.519691 + 00: 00 ':: timestamptz,' Bic ')
Поскольку это исключение уровня dbЯ не могу перехватить его в моем коде, и буфер будет помечен как завершенный (поскольку в коде не было никаких исключений).
Простое решение здесь - не запускать асинхронные буферы, а только один ввремя.
Вот моя часть кода:
@atomic
def create(self, data):
...
brand_obj = Brand.objects.update_or_create(
name=brand['name'],
defaults={
'name': brand['name']
}
)[0]
...
, который вызывается через:
process_incoming.delay(buffer.pk)
Можно ли запускать мои буферы асинхронно, не нажимаяограничения уровня БД?