mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-06 16:31:57 +08:00
## Background Currently you can "dismiss" problem checks on the dashboard, but if the problem persists it will show up again on the next reload, which is confusing. There was previously some discussion about adding a feature to "snooze" problem checks, but I think even with that it remains a bit too opaque. You'd need to spelunk around in the console to try and figure out what is going on. ## What is this change? This PR does a couple of things: ### 1. Replace Dismiss with Ignore Hitting ignore will prevent the problem check from creating new admin notices until it has been unignored from the new problem checks page. **Screenshot** <img width="395" height="61" alt="Screenshot 2026-04-05 at 4 37 39 PM" src="https://github.com/user-attachments/assets/4816fd04-046b-441e-9471-c160dd3f82b9" /> ### 2. Add a new problem check page This page provides a list of problem checks with information on whether they are passing or failing, and when they were last run. You can also ignore or unignore (watch) problem checks from here. **Screenshot** <img width="600" height="200" alt="Screenshot 2026-04-05 at 4 26 37 PM" src="https://github.com/user-attachments/assets/d8cb2b6a-3f56-409c-97f0-312cb1545654" /> ### 3. Remove the problem check timestamp from the dashboard This timestamp made sense under the previous model, where all checks were run at once and the results cached. With the new model, there's a mix of on-demand and scheduled checks, and having a single timestamp is misleading at best. In practice it's always going to be just the timestamp when you last loaded the dashboard. **Before** <img width="240" height="100" alt="Screenshot 2026-04-05 at 4 30 21 PM" src="https://github.com/user-attachments/assets/1846e024-0042-476e-8b5d-41b6745af75f" /> **After** <img width="210" height="95" alt="Screenshot 2026-04-05 at 4 29 19 PM" src="https://github.com/user-attachments/assets/a39c87c1-c1e3-4621-8219-e3903ba2ada4" />
129 lines
2.8 KiB
Ruby
129 lines
2.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class ProblemCheckTracker < ActiveRecord::Base
|
|
validates :identifier, presence: true, uniqueness: { scope: :target }
|
|
validates :target, presence: true
|
|
validates :blips, presence: true, numericality: { greater_than_or_equal_to: 0 }
|
|
|
|
scope :failing, -> { where("last_problem_at = last_run_at") }
|
|
scope :passing, -> { where("last_success_at = last_run_at") }
|
|
scope :ignored, -> { where.not(ignored_at: nil) }
|
|
scope :watched, -> { where(ignored_at: nil) }
|
|
|
|
before_destroy :silence_the_alarm
|
|
|
|
def self.[](identifier, target = ProblemCheck::NO_TARGET)
|
|
find_or_create_by(identifier:, target:)
|
|
end
|
|
|
|
def ready_to_run?
|
|
next_run_at.blank? || next_run_at.past?
|
|
end
|
|
|
|
def failing?
|
|
last_problem_at == last_run_at
|
|
end
|
|
|
|
def passing?
|
|
last_success_at == last_run_at
|
|
end
|
|
|
|
def ignored?
|
|
ignored_at.present?
|
|
end
|
|
|
|
def watched?
|
|
!ignored?
|
|
end
|
|
|
|
def ignore!
|
|
return if ignored?
|
|
|
|
touch(:ignored_at)
|
|
silence_the_alarm
|
|
end
|
|
|
|
def watch!
|
|
return if watched?
|
|
|
|
update!(ignored_at: nil)
|
|
sound_the_alarm if sound_the_alarm?
|
|
end
|
|
|
|
def problem!(next_run_at: nil, details: {})
|
|
now = Time.current
|
|
|
|
update!(blips: blips + 1, details:, last_run_at: now, last_problem_at: now, next_run_at:)
|
|
|
|
update_notice_details(details)
|
|
|
|
sound_the_alarm if sound_the_alarm?
|
|
end
|
|
|
|
def no_problem!(next_run_at: nil)
|
|
reset(next_run_at:)
|
|
silence_the_alarm
|
|
end
|
|
|
|
def check
|
|
check = ProblemCheck[identifier]
|
|
|
|
return check if check.present?
|
|
|
|
silence_the_alarm
|
|
destroy
|
|
|
|
nil
|
|
end
|
|
|
|
private
|
|
|
|
def reset(next_run_at: nil)
|
|
now = Time.current
|
|
|
|
update!(blips: 0, last_run_at: now, last_success_at: now, next_run_at:)
|
|
end
|
|
|
|
def update_notice_details(details)
|
|
admin_notice.where(identifier:).update_all(details: details.merge(target:))
|
|
end
|
|
|
|
def sound_the_alarm?
|
|
watched? && failing? && blips > check.max_blips
|
|
end
|
|
|
|
def sound_the_alarm
|
|
admin_notice.create_with(
|
|
priority: check.priority,
|
|
details: details.merge(target:),
|
|
).find_or_create_by(identifier:)
|
|
end
|
|
|
|
def silence_the_alarm
|
|
admin_notice.where(identifier:).delete_all
|
|
end
|
|
|
|
def admin_notice
|
|
AdminNotice.problem.where("details->>'target' = ?", target)
|
|
end
|
|
end
|
|
|
|
# == Schema Information
|
|
#
|
|
# Table name: problem_check_trackers
|
|
#
|
|
# id :bigint not null, primary key
|
|
# blips :integer default(0), not null
|
|
# details :json
|
|
# identifier :string not null
|
|
# ignored_at :datetime
|
|
# last_problem_at :datetime
|
|
# last_run_at :datetime
|
|
# last_success_at :datetime
|
|
# next_run_at :datetime
|
|
# target :string default("__NULL__"), not null
|
|
#
|
|
# Indexes
|
|
#
|
|
# index_problem_check_trackers_on_identifier_and_target (identifier,target) UNIQUE
|
|
#
|