Rails 5-Sidekiq工作人员显示工作已完成,但什么也没发生



我使用Sidekiq处理带有sidekiq-statussidekiq-entgem的延迟作业。我已经创建了一个工作者,当用户是adult并且具有minor: true时,该工作者负责将minor状态更新为false。这名工人应该在美国东部时间每天午夜被解雇。如下所示:

#initializers/sidekiq.rb
config.periodic do |mgr|
# every day between midnight 0 5 * * *
mgr.register("0 5 * * *", MinorWorker)
end
#app/workers/minor_worker.rb
class MinorWorker
include Sidekiq::Worker
def perform
User.adults.where(minor: true).remove_minor_status
rescue => e
Rails.logger.error("Unable to update minor field. Exception: #{e.message} : #{e.backtrace.join('n')}")
end
end
#models/user.rb
class User < ApplicationRecord
scope :adults,          -> { where('date_of_birth <= ?', 18.years.ago) }
def self.remove_minor_status
update(minor: false)
end
end

不,我想在我的本地机器上检查这个——为此,我使用gem 'timecop'进行时间旅行:

#application.rb
config.time_zone = 'Eastern Time (US & Canada)'
#config/environments/development.rb
config.after_initialize do
t = Time.local(2021, 12, 21, 23, 59, 0)
Timecop.travel(t)
end

bundle exec sidekiqbundle exec rails s启动sidekiq后,我正在等待一分钟,我看到那个工人出现了:

2021-12-21T22:59:00.130Z 25711 TID-ovvzr9828 INFO: Managing 3 periodic jobs
2021-12-21T23:00:00.009Z 25711 TID-ovw69k4ao INFO: Enqueued periodic job SettlementWorker with JID ddab15264f81e0b417e7dd83 for 2021-12-22 00:00:00 +0100
2021-12-21T23:00:00.011Z 25711 TID-ovw69k4ao INFO: Enqueued periodic job MinorWorker with JID 0bcd6b76d6ee4ff9e7850b35 for 2021-12-22 00:00:00 +0100

但它什么也没做,用户的次要状态仍然设置为minor: true:

2.4.5 :002 > User.last.date_of_birth
=> Mon, 22 Dec 2003
2.4.5 :001 > User.last.minor
=> true

我错过什么了吗?

编辑

我必须补充一点,当我试图在rails c上给这个工人打电话时,一切都很好。我甚至有一个RSpec测试也通过了:

RSpec.describe MinorWorker, type: :worker do
subject(:perform) { described_class.new.perform }
context 'when User has minor status' do
let(:user1) { create(:user, minor: true) }
it 'removes minor status' do
expect { perform }.to change { user1.reload.minor }.from(true).to(false)
end
context 'when user is adult' do
let(:registrant2) { create(:registrant) }
it 'not change minor status' do
expect(registrant2.reload.minor).to eq(false)
end
end
end
end

由于这是类方法update无法在中工作

def self.remove_minor_status
update(minor: false)
end

使用#update_all

def self.remove_minor_status
update_all(minor: false)
end

此外,我认为最好的做法是有一些测试用例来确保方法的工作。

到目前为止,你可以从rails console尝试这种方法,并验证它们是否真的能工作

test "update minor status" do
user = User.create(date_of_birth: 19.years.ago, minor: true)
User.adults.where(minor: true).remove_minor_status
assert_equal user.reload.minor, false
end

我认为您需要单独对每条记录执行update_allupdate,如下所示:

User.adults.where(minor: true).update_all(minor: false)

class MinorWorker
include Sidekiq::Worker
def perform
users = User.adults.where(minor: true)
users.each { |user| user.remove_minor_status }
rescue => e
Rails.logger.error("Unable to update minor field. Exception: #{e.message} : #{e.backtrace.join('n')}")
end
end

您可能还需要考虑将update更改为update!,以便在作业中未被rescue捕获时抛出错误:

def self.remove_minor_status
update!(minor: false)
end

最新更新