scheduler.rb 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. module MonitoringHelper
  3. class HealthChecker
  4. class Scheduler < Backend
  5. include ActionView::Helpers::DateHelper
  6. LAST_EXECUTION_TOLERANCE = 8.minutes
  7. def run_health_check
  8. last_execution
  9. none_running
  10. failed_jobs
  11. end
  12. private
  13. def last_execution
  14. last_execution_scope.each do |scheduler|
  15. next if last_execution_on_time?(scheduler)
  16. response.issues.push "scheduler may not run (last execution of #{scheduler.method} #{time_ago_in_words(scheduler.last_run)} ago) - please contact your system administrator"
  17. break
  18. end
  19. end
  20. def last_execution_scope
  21. ::Scheduler
  22. .where('active = ? AND period > 300', true)
  23. .where.not(last_run: nil)
  24. .order(last_run: :asc, period: :asc)
  25. end
  26. def last_execution_on_time?(scheduler)
  27. expected_next_run = if scheduler.timeplan.present?
  28. calculator = TimeplanCalculation.new(scheduler.timeplan, Setting.get('timezone_default').presence || 'UTC')
  29. intermediary = calculator.next_at(scheduler.last_run)
  30. calculator.next_at(intermediary + 10.minutes)
  31. else
  32. scheduler.last_run + scheduler.period.seconds
  33. end
  34. expected_next_run >= LAST_EXECUTION_TOLERANCE.ago
  35. end
  36. def none_running
  37. return if ::Scheduler.where(active: true).where.not(last_run: nil).exists?
  38. response.issues.push 'scheduler not running'
  39. end
  40. def failed_jobs
  41. ::Scheduler.failed_jobs.each do |job|
  42. response.issues.push "Failed to run scheduled job '#{job.name}'. Cause: #{job.error_message}"
  43. response.actions.add(:restart_failed_jobs)
  44. end
  45. end
  46. end
  47. end
  48. end