discourse/spec/jobs/topic_timer_enqueuer_spec.rb
Martin Brennan c6f2459cc4
FIX: Do not prevent other topic timers running on error (#13665)
There was an issue with the TopicTimerEnqueuer where any timer
that failed to enqueue_typed_job with an error would prevent
all other pending timers after the one that errored from running.

To mitigate this we just capture the error and log it (so we can
still fix it if needed for bug crushing) and proceed with the
rest of the timer enqueues.

The commit https://github.com/discourse/discourse/pull/13544 highlighted
this issue originally in hosted sites.

<!-- NOTE: All pull requests should have tests (rspec in Ruby, qunit in JavaScript). If your code does not include test coverage, please include an explanation of why it was omitted. -->
2021-07-08 12:49:58 +10:00

56 lines
2.1 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Jobs::TopicTimerEnqueuer do
subject { described_class.new }
fab!(:timer1) do
Fabricate(:topic_timer, execute_at: 1.minute.ago, created_at: 1.hour.ago, status_type: TopicTimer.types[:close])
end
fab!(:timer2) do
Fabricate(:topic_timer, execute_at: 1.minute.ago, created_at: 1.hour.ago, status_type: TopicTimer.types[:open])
end
fab!(:future_timer) do
Fabricate(:topic_timer, execute_at: 1.hours.from_now, created_at: 1.hour.ago, status_type: TopicTimer.types[:close])
end
fab!(:deleted_timer) do
Fabricate(:topic_timer, execute_at: 1.minute.ago, created_at: 1.hour.ago, status_type: TopicTimer.types[:close])
end
before do
deleted_timer.trash!
end
it "does not enqueue deleted timers" do
expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: deleted_timer.id })
subject.execute
expect(deleted_timer.topic.reload.closed?).to eq(false)
end
it "does not enqueue future timers" do
expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: future_timer.id })
subject.execute
expect(future_timer.topic.reload.closed?).to eq(false)
end
it "enqueues the related job" do
expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: deleted_timer.id })
expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: future_timer.id })
subject.execute
expect_job_enqueued(job: :close_topic, args: { topic_timer_id: timer1.id })
expect_job_enqueued(job: :open_topic, args: { topic_timer_id: timer2.id })
end
it "does not re-enqueue a job that has already been scheduled ahead of time in sidekiq (legacy topic timers)" do
expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: timer1.id })
Jobs.enqueue_at(1.hours.from_now, :close_topic, topic_timer_id: timer1.id)
subject.execute
end
it "does not fail to enqueue other timers just because one timer errors" do
TopicTimer.any_instance.stubs(:enqueue_typed_job).raises(StandardError).then.returns(true)
expect { subject.execute }.not_to raise_error
end
end