我有大约 10 名工人从事的工作包括以下内容:
user = User.find_or_initialize_by(email: 'some-email@address.com')
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 作业),但我不太确定如何实现这一点,也不知道这是否是一种可建议的方法。
我将不胜感激任何帮助。
编辑
在我的具体情况下,很难将电子邮件参数放入作业中,因为这项作业比上面所说的要复杂一些。该作业实际上是一个导出脚本,其中一部分作业是上面的代码。我认为也不可能将上述功能分离到另一个单独的工作人员中......因为整个工作流程应该是串行的,并且不应并行/异步处理任何部分。该作业只是由另一个作业管理的作业之一,其中最终由主作业管理。