diff --git a/app/jobs/regular/problem_check.rb b/app/jobs/regular/problem_check.rb
index 715cab58541..f20e0cc5ad0 100644
--- a/app/jobs/regular/problem_check.rb
+++ b/app/jobs/regular/problem_check.rb
@@ -13,17 +13,23 @@ module Jobs
retry_count = args[:retry_count].to_i
identifier = args[:check_identifier].to_sym
- check = AdminDashboardData.problem_scheduled_check_klasses[identifier]
+ check = ::ProblemCheck[identifier]
- AdminDashboardData.execute_scheduled_check(identifier) do |problems|
- raise RetrySignal if retry_count < check.max_retries
- end
+ problems = check.call
+ raise RetrySignal if problems.present? && retry_count < check.max_retries
+
+ problems.each { |problem| AdminDashboardData.add_found_scheduled_check_problem(problem) }
rescue RetrySignal
Jobs.enqueue_in(
- check.retry_wait,
+ check.retry_after,
:problem_check,
args.merge(retry_count: retry_count + 1).stringify_keys,
)
+ rescue StandardError => err
+ Discourse.warn_exception(
+ err,
+ message: "A scheduled admin dashboard problem check (#{identifier}) errored.",
+ )
end
end
end
diff --git a/app/jobs/scheduled/problem_checks.rb b/app/jobs/scheduled/problem_checks.rb
index c6540b2c542..8950138faf5 100644
--- a/app/jobs/scheduled/problem_checks.rb
+++ b/app/jobs/scheduled/problem_checks.rb
@@ -2,8 +2,8 @@
module Jobs
# This job runs all of the scheduled problem checks for the admin dashboard
- # on a regular basis. To add a problem check for this scheduled job run
- # call AdminDashboardData.add_scheduled_problem_check
+ # on a regular basis. To add a problem check, add a new class that inherits
+ # the `ProblemCheck` base class.
class ProblemChecks < ::Jobs::Scheduled
sidekiq_options retry: false
@@ -13,7 +13,10 @@ module Jobs
# This way if the problems have been solved in the meantime, then they will
# not be re-added by the relevant checker, and will be cleared.
AdminDashboardData.clear_found_scheduled_check_problems
- AdminDashboardData.execute_scheduled_checks
+
+ ::ProblemCheck.scheduled.each do |check|
+ Jobs.enqueue(:problem_check, check_identifier: check.identifier.to_s)
+ end
end
end
end
diff --git a/app/models/admin_dashboard_data.rb b/app/models/admin_dashboard_data.rb
index 9bacaff5de4..9bec82b49ad 100644
--- a/app/models/admin_dashboard_data.rb
+++ b/app/models/admin_dashboard_data.rb
@@ -3,11 +3,7 @@
class AdminDashboardData
include StatsCacheable
- cattr_reader :problem_syms,
- :problem_blocks,
- :problem_messages,
- :problem_scheduled_check_blocks,
- :problem_scheduled_check_klasses
+ cattr_reader :problem_syms, :problem_blocks, :problem_messages
class Problem
VALID_PRIORITIES = %w[low high].freeze
@@ -84,11 +80,6 @@ class AdminDashboardData
@@problem_blocks << blk if blk
end
- def self.add_scheduled_problem_check(check_identifier, klass = nil, &blk)
- @@problem_scheduled_check_klasses[check_identifier] = klass
- @@problem_scheduled_check_blocks[check_identifier] = blk
- end
-
def self.add_found_scheduled_check_problem(problem)
problems = load_found_scheduled_check_problems
if problem.identifier.present?
@@ -129,57 +120,6 @@ class AdminDashboardData
end
end
- def self.register_default_scheduled_problem_checks
- add_scheduled_problem_check(:group_smtp_credentials, GroupEmailCredentialsCheck) do
- problems = GroupEmailCredentialsCheck.run
- problems.map do |p|
- problem_message =
- I18n.t(
- "dashboard.group_email_credentials_warning",
- {
- base_path: Discourse.base_path,
- group_name: p[:group_name],
- group_full_name: p[:group_full_name],
- error: p[:message],
- },
- )
- Problem.new(
- problem_message,
- priority: "high",
- identifier: "group_#{p[:group_id]}_email_credentials",
- )
- end
- end
- end
-
- def self.execute_scheduled_checks
- problem_scheduled_check_blocks.keys.each do |check_identifier|
- Jobs.enqueue(:problem_check, check_identifier: check_identifier.to_s)
- end
- end
-
- def self.execute_scheduled_check(identifier)
- check = problem_scheduled_check_blocks[identifier]
-
- problems = instance_exec(&check)
-
- yield(problems) if block_given? && problems.present?
-
- Array
- .wrap(problems)
- .compact
- .each do |problem|
- next if !problem.is_a?(Problem)
-
- add_found_scheduled_check_problem(problem)
- end
- rescue StandardError => err
- Discourse.warn_exception(
- err,
- message: "A scheduled admin dashboard problem check (#{identifier}) errored.",
- )
- end
-
##
# We call this method in the class definition below
# so all of the problem checks in this class are registered on
@@ -192,8 +132,6 @@ class AdminDashboardData
def self.reset_problem_checks
@@problem_syms = []
@@problem_blocks = []
- @@problem_scheduled_check_blocks = {}
- @@problem_scheduled_check_klasses = {}
@@problem_messages = %w[
dashboard.bad_favicon_url
@@ -222,8 +160,6 @@ class AdminDashboardData
:translation_overrides_check,
:ember_version_check
- register_default_scheduled_problem_checks
-
add_problem_check { sidekiq_check || queue_size_check }
end
reset_problem_checks
diff --git a/lib/group_email_credentials_check.rb b/lib/group_email_credentials_check.rb
deleted file mode 100644
index f9e9ced842a..00000000000
--- a/lib/group_email_credentials_check.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-##
-# If group SMTP or IMAP has been configured, we want to make sure the
-# credentials are always valid otherwise emails will not be sending out
-# from group inboxes. This check is run as part of scheduled AdminDashboardData
-# problem checks, and if any credentials have issues they will show up on
-# the admin dashboard as a high priority issue.
-class GroupEmailCredentialsCheck
- def self.max_retries = 2
- def self.retry_wait = 30.seconds
-
- def self.run
- errors = []
-
- if SiteSetting.enable_smtp
- Group.with_smtp_configured.find_each do |group|
- errors << try_validate(group) do
- EmailSettingsValidator.validate_smtp(
- host: group.smtp_server,
- port: group.smtp_port,
- username: group.email_username,
- password: group.email_password,
- )
- end
- end
- end
-
- if SiteSetting.enable_imap
- Group.with_imap_configured.find_each do |group|
- errors << try_validate(group) do
- EmailSettingsValidator.validate_imap(
- host: group.smtp_server,
- port: group.smtp_port,
- username: group.email_username,
- password: group.email_password,
- )
- end
- end
- end
-
- errors.compact
- end
-
- def self.try_validate(group, &blk)
- begin
- blk.call
- nil
- rescue *EmailSettingsExceptionHandler::EXPECTED_EXCEPTIONS => err
- {
- group_id: group.id,
- group_name: group.name,
- group_full_name: group.full_name,
- message: EmailSettingsExceptionHandler.friendly_exception_message(err, group.smtp_server),
- }
- rescue => err
- Discourse.warn_exception(
- err,
- message:
- "Unexpected error when checking SMTP credentials for group #{group.id} (#{group.name}).",
- )
- nil
- end
- end
-end
diff --git a/lib/problem_check.rb b/lib/problem_check.rb
new file mode 100644
index 00000000000..8970240e375
--- /dev/null
+++ b/lib/problem_check.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+class ProblemCheck
+ include ActiveSupport::Configurable
+
+ # Determines if the check should be performed at a regular interval, and if
+ # so how often. If left blank, the check will be performed every time the
+ # admin dashboard is loaded, or the data is otherwise requested.
+ #
+ config_accessor :perform_every, default: nil, instance_writer: false
+
+ # How many times the check should retry before registering a problem. Only
+ # works for scheduled checks.
+ #
+ config_accessor :max_retries, default: 2, instance_writer: false
+
+ # The retry delay after a failed check. Only works for scheduled checks with
+ # more than one retry configured.
+ #
+ config_accessor :retry_after, default: 30.seconds, instance_writer: false
+
+ def self.[](key)
+ key = key.to_sym
+
+ checks.find { |c| c.identifier == key }
+ end
+
+ def self.checks
+ descendants
+ end
+
+ def self.scheduled
+ checks.select(&:scheduled?)
+ end
+
+ def self.identifier
+ name.demodulize.underscore.to_sym
+ end
+ delegate :identifier, to: :class
+
+ def self.scheduled?
+ perform_every.present?
+ end
+ delegate :scheduled?, to: :class
+
+ def self.call
+ new.call
+ end
+
+ def call
+ raise NotImplementedError
+ end
+end
diff --git a/lib/problem_check/group_email_credentials.rb b/lib/problem_check/group_email_credentials.rb
new file mode 100644
index 00000000000..7a2c32612b0
--- /dev/null
+++ b/lib/problem_check/group_email_credentials.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+##
+# If group SMTP or IMAP has been configured, we want to make sure the
+# credentials are always valid otherwise emails will not be sending out
+# from group inboxes. This check is run as part of scheduled admin
+# problem checks, and if any credentials have issues they will show up on
+# the admin dashboard as a high priority issue.
+class ProblemCheck::GroupEmailCredentials < ProblemCheck
+ self.perform_every = 30.minutes
+
+ def call
+ [*smtp_errors, *imap_errors]
+ end
+
+ private
+
+ def smtp_errors
+ return [] if !SiteSetting.enable_smtp
+
+ Group.with_smtp_configured.find_each.filter_map do |group|
+ try_validate(group) do
+ EmailSettingsValidator.validate_smtp(
+ host: group.smtp_server,
+ port: group.smtp_port,
+ username: group.email_username,
+ password: group.email_password,
+ )
+ end
+ end
+ end
+
+ def imap_errors
+ return [] if !SiteSetting.enable_imap
+
+ Group.with_imap_configured.find_each.filter_map do |group|
+ try_validate(group) do
+ EmailSettingsValidator.validate_imap(
+ host: group.imap_server,
+ port: group.imap_port,
+ username: group.email_username,
+ password: group.email_password,
+ )
+ end
+ end
+ end
+
+ def try_validate(group, &blk)
+ begin
+ blk.call
+ nil
+ rescue *EmailSettingsExceptionHandler::EXPECTED_EXCEPTIONS => err
+ message =
+ I18n.t(
+ "dashboard.group_email_credentials_warning",
+ {
+ base_path: Discourse.base_path,
+ group_name: group.name,
+ group_full_name: group.full_name,
+ error: EmailSettingsExceptionHandler.friendly_exception_message(err, group.smtp_server),
+ },
+ )
+
+ Problem.new(message, priority: "high", identifier: "group_#{group.id}_email_credentials")
+ rescue => err
+ Discourse.warn_exception(
+ err,
+ message:
+ "Unexpected error when checking SMTP credentials for group #{group.id} (#{group.name}).",
+ )
+ nil
+ end
+ end
+end
diff --git a/lib/problem_check/problem.rb b/lib/problem_check/problem.rb
new file mode 100644
index 00000000000..0fa52456b05
--- /dev/null
+++ b/lib/problem_check/problem.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class ProblemCheck::Problem
+ PRIORITIES = %w[low high].freeze
+
+ attr_reader :message, :priority, :identifier
+
+ def initialize(message, priority: "low", identifier: nil)
+ @message = message
+ @priority = PRIORITIES.include?(priority) ? priority : "low"
+ @identifier = identifier
+ end
+
+ def to_s
+ @message
+ end
+
+ def to_h
+ { message: message, priority: priority, identifier: identifier }
+ end
+ alias_method :attributes, :to_h
+
+ def self.from_h(h)
+ h = h.with_indifferent_access
+
+ return if h[:message].blank?
+
+ new(h[:message], priority: h[:priority], identifier: h[:identifier])
+ end
+end
diff --git a/spec/jobs/problem_check_spec.rb b/spec/jobs/problem_check_spec.rb
index 80108ad593d..8f4d9d60b5f 100644
--- a/spec/jobs/problem_check_spec.rb
+++ b/spec/jobs/problem_check_spec.rb
@@ -3,98 +3,128 @@
RSpec.describe Jobs::ProblemCheck do
after do
Discourse.redis.flushdb
- AdminDashboardData.reset_problem_checks
+
+ ::ProblemCheck.send(:remove_const, "TestCheck")
end
- class TestCheck
- def self.max_retries = 0
- def self.retry_wait = 30.seconds
- end
+ context "when there are problems" do
+ before do
+ ::ProblemCheck::TestCheck =
+ Class.new(::ProblemCheck) do
+ self.max_retries = 0
- it "runs the scheduled problem check that has been added and adds the messages to the load_found_scheduled_check_problems array" do
- AdminDashboardData.add_scheduled_problem_check(:test_identifier, TestCheck) do
- AdminDashboardData::Problem.new("big problem")
+ def call
+ [
+ ::ProblemCheck::Problem.new("Big problem"),
+ ::ProblemCheck::Problem.new(
+ "Yuge problem",
+ priority: "high",
+ identifier: "config_is_a_mess",
+ ),
+ ]
+ end
+ end
end
- described_class.new.execute(check_identifier: :test_identifier)
- problems = AdminDashboardData.load_found_scheduled_check_problems
- expect(problems.count).to eq(1)
- expect(problems.first).to be_a(AdminDashboardData::Problem)
- expect(problems.first.to_s).to eq("big problem")
- end
+ it "adds the messages to the Redis problems array" do
+ described_class.new.execute(check_identifier: :test_check)
- it "can handle the problem check returning multiple problems" do
- AdminDashboardData.add_scheduled_problem_check(:test_identifier, TestCheck) do
- [
- AdminDashboardData::Problem.new("big problem"),
- AdminDashboardData::Problem.new(
- "yuge problem",
- priority: "high",
- identifier: "config_is_a_mess",
- ),
- ]
- end
+ problems = AdminDashboardData.load_found_scheduled_check_problems
- described_class.new.execute(check_identifier: :test_identifier)
- problems = AdminDashboardData.load_found_scheduled_check_problems
- expect(problems.map(&:to_s)).to match_array(["big problem", "yuge problem"])
- end
-
- it "does not add the same problem twice if the identifier already exists" do
- AdminDashboardData.add_scheduled_problem_check(:test_identifier, TestCheck) do
- [
- AdminDashboardData::Problem.new(
- "yuge problem",
- priority: "high",
- identifier: "config_is_a_mess",
- ),
- AdminDashboardData::Problem.new(
- "nasty problem",
- priority: "high",
- identifier: "config_is_a_mess",
- ),
- ]
- end
-
- described_class.new.execute(check_identifier: :test_identifier)
- problems = AdminDashboardData.load_found_scheduled_check_problems
- expect(problems.map(&:to_s)).to match_array(["yuge problem"])
- end
-
- it "schedules a retry if there are attempts remaining" do
- AdminDashboardData.add_scheduled_problem_check(:test_identifier, TestCheck) do
- AdminDashboardData::Problem.new("big problem")
- end
-
- TestCheck.stubs(:max_retries).returns(1)
-
- expect_enqueued_with(
- job: :problem_check,
- args: {
- check_identifier: :test_identifier,
- retry_count: 1,
- },
- ) { described_class.new.execute(check_identifier: :test_identifier) }
- end
-
- it "does not schedule a retry if there are no more attempts remaining" do
- AdminDashboardData.add_scheduled_problem_check(:test_identifier, TestCheck) do
- AdminDashboardData::Problem.new("big problem")
- end
-
- TestCheck.stubs(:max_retries).returns(1)
-
- expect_not_enqueued_with(job: :problem_check) do
- described_class.new.execute(check_identifier: :test_identifier, retry_count: 1)
+ expect(problems.map(&:to_s)).to contain_exactly("Big problem", "Yuge problem")
end
end
- it "handles errors from a troublesome check" do
- AdminDashboardData.add_scheduled_problem_check(:test_identifier, TestCheck) do
- raise StandardError.new("something went wrong")
+ context "with multiple problems with the same identifier" do
+ before do
+ ::ProblemCheck::TestCheck =
+ Class.new(::ProblemCheck) do
+ self.max_retries = 0
+
+ def call
+ [
+ ::ProblemCheck::Problem.new(
+ "Yuge problem",
+ priority: "high",
+ identifier: "config_is_a_mess",
+ ),
+ ::ProblemCheck::Problem.new(
+ "Nasty problem",
+ priority: "high",
+ identifier: "config_is_a_mess",
+ ),
+ ]
+ end
+ end
end
- described_class.new.execute(check_identifier: :test_identifier)
- expect(AdminDashboardData.load_found_scheduled_check_problems.count).to eq(0)
+ it "does not add the same problem twice" do
+ described_class.new.execute(check_identifier: :test_check)
+
+ problems = AdminDashboardData.load_found_scheduled_check_problems
+
+ expect(problems.map(&:to_s)).to match_array(["Yuge problem"])
+ end
+ end
+
+ context "when there are retries remaining" do
+ before do
+ ::ProblemCheck::TestCheck =
+ Class.new(::ProblemCheck) do
+ self.max_retries = 2
+
+ def call
+ [::ProblemCheck::Problem.new("Yuge problem")]
+ end
+ end
+ end
+
+ it "schedules a retry" do
+ expect_enqueued_with(
+ job: :problem_check,
+ args: {
+ check_identifier: :test_check,
+ retry_count: 1,
+ },
+ ) { described_class.new.execute(check_identifier: :test_check) }
+ end
+ end
+
+ context "when there are no retries remaining" do
+ before do
+ ::ProblemCheck::TestCheck =
+ Class.new(::ProblemCheck) do
+ self.max_retries = 1
+
+ def call
+ [::ProblemCheck::Problem.new("Yuge problem")]
+ end
+ end
+ end
+
+ it "does not schedule a retry" do
+ expect_not_enqueued_with(job: :problem_check) do
+ described_class.new.execute(check_identifier: :test_identifier, retry_count: 1)
+ end
+ end
+ end
+
+ context "when the check unexpectedly errors out" do
+ before do
+ ::ProblemCheck::TestCheck =
+ Class.new(::ProblemCheck) do
+ self.max_retries = 1
+
+ def call
+ raise StandardError.new("Something went wrong")
+ end
+ end
+ end
+
+ it "does not add a problem to the Redis array" do
+ described_class.new.execute(check_identifier: :test_check)
+
+ expect(AdminDashboardData.load_found_scheduled_check_problems).to be_empty
+ end
end
end
diff --git a/spec/jobs/problem_checks_spec.rb b/spec/jobs/problem_checks_spec.rb
index 38b471dc5e2..2e1c30b6213 100644
--- a/spec/jobs/problem_checks_spec.rb
+++ b/spec/jobs/problem_checks_spec.rb
@@ -1,31 +1,37 @@
# frozen_string_literal: true
RSpec.describe Jobs::ProblemChecks do
- before { Jobs.run_immediately! }
+ before do
+ ::ProblemCheck::ScheduledCheck =
+ Class.new(ProblemCheck) do
+ self.perform_every = 30.minutes
+
+ def call = []
+ end
+
+ ::ProblemCheck::NonScheduledCheck = Class.new(ProblemCheck) { def call = [] }
+ end
after do
Discourse.redis.flushdb
AdminDashboardData.reset_problem_checks
+
+ ProblemCheck.send(:remove_const, "ScheduledCheck")
+ ProblemCheck.send(:remove_const, "NonScheduledCheck")
end
- class TestCheck
- def self.max_retries = 0
- def self.retry_wait = 0.seconds
- end
-
- it "starts with a blank slate every time the checks are run to avoid duplicate problems and to clear no longer firing problems" do
- problem_should_fire = true
- AdminDashboardData.reset_problem_checks
- AdminDashboardData.add_scheduled_problem_check(:test_identifier, TestCheck) do
- if problem_should_fire
- problem_should_fire = false
- AdminDashboardData::Problem.new("yuge problem", priority: "high")
- end
+ it "schedules the individual scheduled checks" do
+ expect_enqueued_with(job: :problem_check, args: { check_identifier: "scheduled_check" }) do
+ described_class.new.execute([])
end
+ end
- described_class.new.execute(nil)
- expect(AdminDashboardData.load_found_scheduled_check_problems.count).to eq(1)
- described_class.new.execute(nil)
- expect(AdminDashboardData.load_found_scheduled_check_problems.count).to eq(0)
+ it "does not schedule non-scheduled checks" do
+ expect_not_enqueued_with(
+ job: :problem_check,
+ args: {
+ check_identifier: "non_scheduled_check",
+ },
+ ) { described_class.new.execute([]) }
end
end
diff --git a/spec/lib/group_email_credentials_check_spec.rb b/spec/lib/problem_check/group_email_credentials_spec.rb
similarity index 58%
rename from spec/lib/group_email_credentials_check_spec.rb
rename to spec/lib/problem_check/group_email_credentials_spec.rb
index 603c1a44df3..3d3a74d9cfa 100644
--- a/spec/lib/group_email_credentials_check_spec.rb
+++ b/spec/lib/problem_check/group_email_credentials_spec.rb
@@ -3,16 +3,16 @@
require "net/smtp"
require "net/imap"
-RSpec.describe GroupEmailCredentialsCheck do
+RSpec.describe ProblemCheck::GroupEmailCredentials do
fab!(:group1) { Fabricate(:group) }
fab!(:group2) { Fabricate(:smtp_group) }
fab!(:group3) { Fabricate(:imap_group) }
- describe "#run" do
+ describe "#call" do
it "does nothing if SMTP is disabled for the site" do
expect_no_validate_any
SiteSetting.enable_smtp = false
- expect(described_class.run).to eq([])
+ expect(described_class.new.call).to eq([])
end
context "with smtp and imap enabled for the site" do
@@ -25,10 +25,10 @@ RSpec.describe GroupEmailCredentialsCheck do
expect_no_validate_any
group2.update!(smtp_enabled: false)
group3.update!(smtp_enabled: false, imap_enabled: false)
- expect(described_class.run).to eq([])
+ expect(described_class.new.call).to eq([])
end
- it "returns an error message and the group ID if the group's SMTP settings error" do
+ it "returns a problem with the group's SMTP settings error" do
EmailSettingsValidator
.expects(:validate_smtp)
.raises(Net::SMTPAuthenticationError.new("bad credentials"))
@@ -37,15 +37,13 @@ RSpec.describe GroupEmailCredentialsCheck do
.at_least_once
EmailSettingsValidator.stubs(:validate_imap).returns(true)
- expect(described_class.run).to eq(
- [
- {
- group_full_name: group2.full_name,
- group_name: group2.name,
- group_id: group2.id,
- message: I18n.t("email_settings.smtp_authentication_error"),
- },
- ],
+ expect(described_class.new.call).to contain_exactly(
+ have_attributes(
+ identifier: "group_#{group2.id}_email_credentials",
+ priority: "high",
+ message:
+ "There was an issue with the email credentials for the group . No emails will be sent from the group inbox until this problem is addressed. There was an issue with the SMTP credentials provided, check the username and password and try again.",
+ ),
)
end
@@ -56,15 +54,13 @@ RSpec.describe GroupEmailCredentialsCheck do
.raises(Net::IMAP::NoResponseError.new(stub(data: stub(text: "Invalid credentials"))))
.once
- expect(described_class.run).to eq(
- [
- {
- group_full_name: group3.full_name,
- group_name: group3.name,
- group_id: group3.id,
- message: I18n.t("email_settings.imap_authentication_error"),
- },
- ],
+ expect(described_class.new.call).to contain_exactly(
+ have_attributes(
+ identifier: "group_#{group3.id}_email_credentials",
+ priority: "high",
+ message:
+ "There was an issue with the email credentials for the group . No emails will be sent from the group inbox until this problem is addressed. There was an issue with the IMAP credentials provided, check the username and password and try again.",
+ ),
)
end
@@ -73,7 +69,7 @@ RSpec.describe GroupEmailCredentialsCheck do
EmailSettingsValidator.stubs(:validate_smtp).returns(true)
EmailSettingsValidator.expects(:validate_imap).never
- expect(described_class.run).to eq([])
+ expect(described_class.new.call).to eq([])
end
end
end
diff --git a/spec/lib/problem_check_spec.rb b/spec/lib/problem_check_spec.rb
new file mode 100644
index 00000000000..9df52fb3a62
--- /dev/null
+++ b/spec/lib/problem_check_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+RSpec.describe ProblemCheck do
+ # rubocop:disable RSpec/BeforeAfterAll
+ before(:all) do
+ ScheduledCheck = Class.new(described_class) { self.perform_every = 30.minutes }
+ UnscheduledCheck = Class.new(described_class)
+ end
+
+ after(:all) do
+ Object.send(:remove_const, ScheduledCheck.name)
+ Object.send(:remove_const, UnscheduledCheck.name)
+ end
+ # rubocop:enable RSpec/BeforeAfterAll
+
+ let(:scheduled_check) { ScheduledCheck }
+ let(:unscheduled_check) { UnscheduledCheck }
+
+ describe ".[]" do
+ it { expect(described_class[:scheduled_check]).to eq(scheduled_check) }
+ it { expect(described_class[:foo]).to eq(nil) }
+ end
+
+ describe ".identifier" do
+ it { expect(scheduled_check.identifier).to eq(:scheduled_check) }
+ end
+
+ describe ".checks" do
+ it { expect(described_class.checks).to contain_exactly(scheduled_check, unscheduled_check) }
+ end
+
+ describe ".scheduled" do
+ it { expect(described_class.scheduled).to contain_exactly(scheduled_check) }
+ end
+
+ describe ".scheduled?" do
+ it { expect(scheduled_check).to be_scheduled }
+ it { expect(unscheduled_check).to_not be_scheduled }
+ end
+end
diff --git a/spec/models/admin_dashboard_data_spec.rb b/spec/models/admin_dashboard_data_spec.rb
index be87adfa960..fd5d675a9ea 100644
--- a/spec/models/admin_dashboard_data_spec.rb
+++ b/spec/models/admin_dashboard_data_spec.rb
@@ -82,49 +82,6 @@ RSpec.describe AdminDashboardData do
include_examples "stats cacheable"
end
- describe ".execute_scheduled_checks" do
- let(:blk) { -> {} }
-
- before { AdminDashboardData.add_scheduled_problem_check(:foo, &blk) }
- after { AdminDashboardData.reset_problem_checks }
-
- it do
- expect_enqueued_with(job: :problem_check, args: { check_identifier: :foo }) do
- AdminDashboardData.execute_scheduled_checks
- end
- end
- end
-
- describe ".execute_scheduled_check" do
- context "when problems are found" do
- let(:blk) { -> { self::Problem.new("Problem") } }
-
- before do
- AdminDashboardData.add_scheduled_problem_check(:foo, &blk)
- AdminDashboardData.expects(:add_found_scheduled_check_problem).once
- end
-
- after { AdminDashboardData.reset_problem_checks }
-
- it do
- expect(described_class.execute_scheduled_check(:foo)).to all(be_a(described_class::Problem))
- end
- end
-
- context "when check errors out" do
- let(:blk) { -> { raise StandardError } }
-
- before do
- AdminDashboardData.add_scheduled_problem_check(:foo, &blk)
- Discourse.expects(:warn_exception).once
- end
-
- after { AdminDashboardData.reset_problem_checks }
-
- it { expect(described_class.execute_scheduled_check(:foo)).to eq(nil) }
- end
- end
-
describe "#problem_message_check" do
let(:key) { AdminDashboardData.problem_messages.first }