mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-04 01:34:26 +08:00
Scheduled problem checks with multiple targets are not honouring the `run_every` configuration. For checks with multiple targets, all targets are checked in a single instance of the problem check. However, we have one problem check tracker per target. This mismatch results in the `#ready_to_run?` method always creating a tracker with no target when being checked. This commit fixes that by: **Expect checks to operate on a single target.** This change makes it so that instances of a `ProblemCheck` class are initialized with a target. So instead of 1-N we now have an N-N relationship between checks and trackers. Each instance can access their `target` through an attribute of the same name. This also means problem checks are back to returning a singular `Problem` or `nil`, instead of `[Problem]` or `[]`. For scheduled checks, this means that `ScheduleProblemChecks` now enqueues `N` jobs (where `N` is the number of targets) per check instead of `1` job per check. **Update existing targeted checks to operate on a single target.** This is essentially just removing the loop inside the check.
112 lines
3 KiB
Ruby
112 lines
3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe Jobs::RunProblemCheck do
|
|
after { Discourse.redis.flushdb }
|
|
|
|
context "when there are problems" do
|
|
around do |example|
|
|
ProblemCheck::TestCheck =
|
|
Class.new(ProblemCheck) do
|
|
self.perform_every = 30.minutes
|
|
self.max_retries = 0
|
|
|
|
def call
|
|
ProblemCheck::Problem.new("Big problem")
|
|
end
|
|
end
|
|
|
|
stub_const(ProblemCheck, "CORE_PROBLEM_CHECKS", [ProblemCheck::TestCheck], &example)
|
|
|
|
ProblemCheck.send(:remove_const, "TestCheck")
|
|
end
|
|
|
|
it "updates the problem check tracker" do
|
|
expect {
|
|
described_class.new.execute(
|
|
check_identifier: "test_check",
|
|
retry_count: 0,
|
|
target: ProblemCheck::NO_TARGET,
|
|
)
|
|
}.to change { ProblemCheckTracker.failing.count }.by(1)
|
|
end
|
|
end
|
|
|
|
context "when there are retries remaining" do
|
|
around do |example|
|
|
ProblemCheck::TestCheck =
|
|
Class.new(ProblemCheck) do
|
|
self.perform_every = 30.minutes
|
|
self.max_retries = 2
|
|
|
|
def call
|
|
ProblemCheck::Problem.new("Yuge problem")
|
|
end
|
|
end
|
|
|
|
stub_const(ProblemCheck, "CORE_PROBLEM_CHECKS", [ProblemCheck::TestCheck], &example)
|
|
|
|
ProblemCheck.send(:remove_const, "TestCheck")
|
|
end
|
|
|
|
it "does not yet update the problem check tracker" do
|
|
expect {
|
|
described_class.new.execute(
|
|
check_identifier: "test_check",
|
|
retry_count: 1,
|
|
target: ProblemCheck::NO_TARGET,
|
|
)
|
|
}.not_to change { ProblemCheckTracker.where("blips > ?", 0).count }
|
|
end
|
|
|
|
it "schedules a retry" do
|
|
expect_enqueued_with(
|
|
job: :run_problem_check,
|
|
args: {
|
|
check_identifier: "test_check",
|
|
retry_count: 1,
|
|
target: ProblemCheck::NO_TARGET,
|
|
},
|
|
) do
|
|
described_class.new.execute(check_identifier: "test_check", target: ProblemCheck::NO_TARGET)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when there are no retries remaining" do
|
|
around do |example|
|
|
ProblemCheck::TestCheck =
|
|
Class.new(ProblemCheck) do
|
|
self.perform_every = 30.minutes
|
|
self.max_retries = 1
|
|
|
|
def call
|
|
ProblemCheck::Problem.new("Yuge problem")
|
|
end
|
|
end
|
|
|
|
stub_const(ProblemCheck, "CORE_PROBLEM_CHECKS", [ProblemCheck::TestCheck], &example)
|
|
|
|
ProblemCheck.send(:remove_const, "TestCheck")
|
|
end
|
|
|
|
it "updates the problem check tracker" do
|
|
expect {
|
|
described_class.new.execute(
|
|
check_identifier: "test_check",
|
|
retry_count: 1,
|
|
target: ProblemCheck::NO_TARGET,
|
|
)
|
|
}.to change { ProblemCheckTracker.where("blips > ?", 0).count }.by(1)
|
|
end
|
|
|
|
it "does not schedule a retry" do
|
|
expect_not_enqueued_with(job: :run_problem_check) do
|
|
described_class.new.execute(
|
|
check_identifier: "test_check",
|
|
retry_count: 1,
|
|
target: ProblemCheck::NO_TARGET,
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|