scheduler.rb 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. # Copyright (C) 2012-2024 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. .reorder(last_run: :asc, period: :asc)
  25. end
  26. def last_execution_deadline(scheduler)
  27. return scheduler.last_run if scheduler.timeplan.blank?
  28. calculator = TimeplanCalculation.new(scheduler.timeplan, Setting.get('timezone_default'))
  29. intermediary = calculator.next_at(scheduler.last_run + 10.minutes)
  30. calculator.next_at(intermediary + 10.minutes)
  31. end
  32. def last_execution_on_time?(scheduler)
  33. return false if scheduler.last_run.blank?
  34. last_execution_deadline(scheduler) + scheduler.period.seconds >= 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