У меня есть около 10 рабочих, которые выполняют работу, которая включает в себя следующее:
user = User.find_or_initialize_by(email: '[email protected]')
if user.new_record?
# ... some code here that does something taking around 5 seconds or so
elsif user.persisted?
# ... some code here that does something taking around 5 seconds or so
end
user.save
Проблема в том, что в определенное время два или более воркера запускают этот код в точное время, и, таким образом, позже я узнал, что у двух или более Пользователей одинаковые email
, в которых я всегда должен заканчивать только уникальные электронные письма.
В моей ситуации невозможно создать уникальные индексы БД для email
, так как уникальные адреса электронной почты являются условными — некоторые пользователи должны иметь уникальный адрес электронной почты, а некоторые — нет.
Стоит отметить, что моя модель User
имеет проверки уникальности, но это все равно не помогает мне, потому что между .find_or_initialize_by
и .save
есть код, который зависит от того, создан ли уже пользовательский объект или нет.
Я пробовал пессимистическую и оптимистическую блокировку, но это мне не помогло, или, может быть, я просто не реализовал ее должным образом... если у вас есть предложения по этому поводу.
Решение, о котором я могу думать, состоит в том, чтобы блокировать другие потоки (задания Sidekiq) всякий раз, когда эти строки кода выполняются, но я не слишком уверен, как это реализовать, и я не знаю, является ли это даже рекомендуемым подходом.
Буду признателен за любую помощь.
РЕДАКТИРОВАТЬ
В моем конкретном случае будет сложно указать параметр электронной почты в задании, так как это задание немного сложнее, чем то, что было только что сказано выше. На самом деле задание представляет собой сценарий экспорта, в котором часть задания представляет собой код, приведенный выше. Я не думаю, что также возможно разделить вышеуказанную функциональность на другого отдельного работника... поскольку весь поток заданий должен быть последовательным и никакие части не должны обрабатываться параллельно/асинхронно. Это задание является лишь одним из заданий, управляемых другим заданием, в котором в конечном счете управляется главным заданием.