scheduler_agent.rb 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. require 'fugit'
  2. module Agents
  3. class SchedulerAgent < Agent
  4. include AgentControllerConcern
  5. cannot_be_scheduled!
  6. cannot_receive_events!
  7. cannot_create_events!
  8. @@second_precision_enabled = ENV['ENABLE_SECOND_PRECISION_SCHEDULE'] == 'true'
  9. cattr_reader :second_precision_enabled
  10. description <<~MD
  11. The Scheduler Agent periodically takes an action on target Agents according to a user-defined schedule.
  12. # Action types
  13. Set `action` to one of the action types below:
  14. * `run`: Target Agents are run at intervals, except for those disabled.
  15. * `disable`: Target Agents are disabled (if not) at intervals.
  16. * `enable`: Target Agents are enabled (if not) at intervals.
  17. * If the option `drop_pending_events` is set to `true`, pending events will be cleared before the agent is enabled.
  18. # Targets
  19. Select Agents that you want to run periodically by this SchedulerAgent.
  20. # Schedule
  21. Set `schedule` to a schedule specification in the [cron](http://en.wikipedia.org/wiki/Cron) format.
  22. For example:
  23. * `0 22 * * 1-5`: every day of the week at 22:00 (10pm)
  24. * `*/10 8-11 * * *`: every 10 minutes from 8:00 to and not including 12:00
  25. This variant has several extensions as explained below.
  26. ## Timezones
  27. You can optionally specify a timezone (default: `#{Time.zone.name}`) after the day-of-week field using the labels in the [tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
  28. * `0 22 * * 1-5 Europe/Paris`: every day of the week when it's 22:00 in Paris
  29. * `0 22 * * 1-5 Etc/GMT+2`: every day of the week when it's 22:00 in GMT+2
  30. ## Seconds
  31. You can optionally specify seconds before the minute field.
  32. * `*/30 * * * * *`: every 30 seconds
  33. #{"Only multiples of fifteen are allowed as values for the seconds field, i.e. `*/15`, `*/30`, `15,45` etc." unless second_precision_enabled}
  34. ## Last day of month
  35. `L` signifies "last day of month" in `day-of-month`.
  36. * `0 22 L * *`: every month on the last day at 22:00
  37. ## Weekday names
  38. You can use three letter names instead of numbers in the `weekdays` field.
  39. * `0 22 * * Sat,Sun`: every Saturday and Sunday, at 22:00
  40. ## Nth weekday of the month
  41. You can specify "nth weekday of the month" like this.
  42. * `0 22 * * Sun#1,Sun#2`: every first and second Sunday of the month, at 22:00
  43. * `0 22 * * Sun#L1`: every last Sunday of the month, at 22:00
  44. MD
  45. def default_options
  46. super.update({
  47. 'schedule' => '0 * * * *',
  48. })
  49. end
  50. def working?
  51. true
  52. end
  53. def validate_options
  54. if (spec = options['schedule']).present?
  55. begin
  56. cron = Fugit::Cron.new(spec) or raise ArgumentError
  57. unless second_precision_enabled || (cron.seconds - [0, 15, 30, 45, 60]).empty?
  58. errors.add(:base, "second precision schedule is not allowed in this service")
  59. end
  60. rescue ArgumentError
  61. errors.add(:base, "invalid schedule")
  62. end
  63. else
  64. errors.add(:base, "schedule is missing")
  65. end
  66. end
  67. before_save do
  68. self.memory.delete('scheduled_at') if self.options_changed?
  69. end
  70. end
  71. end