使用Sidekiq作业的Rails 4.2 ActiveJob失败,然后在Heroku上成功重试

时间:2015-06-05 19:44:13

标签: ruby-on-rails activerecord heroku sidekiq puma

实际结果:

我们收到的失败邮件工作显示在sidekiq web UI(使用sidekiq-failures gem),大约一分钟后成功重试。

失败错误:

ActiveRecord::RecordNotFound: Couldn't find User with 'id'=234

预期:

我们希望sidekiq工作人员能够立即成功而不会失败,并且稍后会(尽管已成功)重试。

设置:Heroku Cedar-14,Rails 4.2,Puma 2.11.2,Sidekiq 3.3.4,Sidekiq-failures 0.4.4

配置/初始化/ sidekiq.rb:

Sidekiq.configure_server do |config|
  database_url = ENV['DATABASE_URL']
  if database_url
    ENV['DATABASE_URL'] = "#{database_url}?pool=15"
    ActiveRecord::Base.establish_connection
  end
end

配置/ puma.rb:

workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['MAX_THREADS'] || 5)
threads threads_count, threads_count

preload_app!

rackup      DefaultRackup
port        ENV['PORT']     || 3000
environment ENV['RACK_ENV'] || 'development'

on_worker_boot do
  ActiveRecord::Base.establish_connection

end

配置/ sidekiq.yml

---
:concurrency: 25
:queues:
  - default
  - mailers
  - [low, 1]
  - [med, 2]
  - [high, 3]

电子邮件是通过控制器操作中的服务运行触发的:

应用/服务/ user_events.rb

@user = User.find(234)
UserMailer.send_email(@user.id).deliver_later

应用/邮寄者/ user_mailer.rb

  def send_email(user_id)
    @user = User.find(user_id)

    # mandrill_headers
    headers['X-MC-Track'] = "opens, clicks_all"
    headers['X-MC-Tags'] = ['user-event']

    mail(to: @user.email, subject: "Hi", css: ["email"])
  end

2 个答案:

答案 0 :(得分:2)

@user是新创建的记录吗?如果是这样,我的预感是您在提交当前数据库事务之前将sidekiq电子邮件作业排入队列。

在这种情况下,新用户存在于您的Rails事务中,但连接到数据库的其他进程尚未看到它,因为新用户记录尚未提交到数据库。当sidekiq运行电子邮件作业(它在与Rails应用程序不同的进程中运行)时,它会尝试加载用户并获得RecordNotFound

解决方案是将sidekiq作业排在之后(之后)数据库事务。如果您使用ActiveRecord回调,则表示您应使用after_commit而不是after_create

来自sidekiq FAQ:https://github.com/mperham/sidekiq/wiki/FAQ#why-am-i-seeing-a-lot-of-cant-find-modelname-with-id12345-errors-with-sidekiq

答案 1 :(得分:0)

问题解决了。事实证明,heroku回滚还原了一个环境变量。