Sidekiq Active Job数据库回滚时出错

时间:2018-03-20 23:38:01

标签: ruby-on-rails ruby-on-rails-5 sidekiq rails-api

我注意到当Sidekiq / Active Job由于抛出错误而失败时,会回滚作业期间发生的任何数据库更改。这似乎是使工作成为幂等的有意识的特征。

我的问题是,作业运行的方法可以向用户发送电子邮件,并使用数据库修改来防止重新发送电子邮件。如果回滚数据库更改,则只要重试作业,就会重新发送电子邮件。

这大致是我的工作:

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input type="text" data-bind="gatedValue: myNumber, gatedValidator: myValidator" />

计划使用sidekiq-scheduler定期运行作业。我使用的是rails-api v5。

我添加了class ProcessPaymentsJob < ApplicationJob queue_as :default def perform(*args) begin # This can send emails to users. PaymentProcessor.perform rescue StandardError => error puts 'PaymentsJob failed, ignoring' puts error end end end 以尝试阻止作业回滚数据库更改但仍然会发生。

我想到,也许这不是Sidekiq问题,而是Rails的一个功能。

这是防止用户通过电子邮件发送垃圾邮件的最佳解决方案吗?

2 个答案:

答案 0 :(得分:0)

您可以在PaymentProcessor内的事务中包装数据库更改,挽救数据库回滚,并且只有在事务成功时才发送电子邮件。有点像这样:

# ../payment_processor.rb

def perform
  ActiveRecord::Base.transaction do
    # AllTheThings.save!
  end
rescue ActiveRecord::RecordInvalid => exception
  # if things fail to save, handle the exception however you like
else
  # if no exception is raised, send your email
end

答案 1 :(得分:0)

听起来你的后台工作做得太多了。如果发送电子邮件与作业是否成功无关,则应将工作分成两个工作:一个用于发送电子邮件,另一个用于执行其他处理工作。

或者,您可以使用Sidekiq批处理并使上面的第一个作业依赖于第二个成功执行。

快乐的Sidekiq'ing!