lib/config_skeleton.rb in config_skeleton-2.0.0 vs lib/config_skeleton.rb in config_skeleton-2.1.0
- old
+ new
@@ -205,15 +205,19 @@
#
def self.watches
@watches || []
end
- def initialize(*_)
+ def initialize(*_, metrics:, config:)
super
initialize_config_skeleton_metrics
@trigger_regen_r, @trigger_regen_w = IO.pipe
@terminate_r, @terminate_w = IO.pipe
+
+ raise "cooldown_duration invalid" if cooldown_duration < 0
+ raise "sleep_duration invalid" if sleep_duration < 0
+ raise "sleep_duration must not be less than cooldown_duration" if sleep_duration < cooldown_duration
end
# Expose the write pipe which can be written to to trigger a config
# regeneration with a forced reload; a similar mechanism is used for
# shutdown but in that case writes are managed internally.
@@ -240,15 +244,20 @@
watch(*self.class.watches)
logger.debug(logloc) { "notifier fd is #{notifier.to_io.inspect}" }
loop do
- if ios = IO.select(
- [notifier.to_io, @terminate_r, @trigger_regen_r],
- [], [],
- sleep_duration.tap { |d| logger.debug(logloc) { "Sleeping for #{d} seconds" } }
- )
+ if cooldown_duration > 0
+ logger.debug(logloc) { "Sleeping for #{cooldown_duration} seconds (cooldown)" }
+ IO.select([@terminate_r], [], [], cooldown_duration)
+ end
+
+ timeout = sleep_duration - cooldown_duration
+ logger.debug(logloc) { "Sleeping for #{timeout} seconds unless interrupted" }
+ ios = IO.select([notifier.to_io, @terminate_r, @trigger_regen_r], [], [], timeout)
+
+ if ios
if ios.first.include?(notifier.to_io)
logger.debug(logloc) { "inotify triggered" }
notifier.process
regenerate_config(force_reload: true)
elsif ios.first.include?(@terminate_r)
@@ -442,9 +451,28 @@
# @return [Integer] the number of seconds to sleep for. This *must not* be
# negative, lest you create a tear in the space-time continuum.
#
def sleep_duration
60
+ end
+
+ # How long to ignore signals/notifications after a config regeneration
+ #
+ # Hammering a downstream service with reload requests is often a bad idea.
+ # This method exists to allow subclasses to define a 'cooldown' duration.
+ # After each config regeneration, the config generator will sleep for this
+ # duration, regardless of any CONT signals or inotify events. Those events
+ # will be queued up, and processed at the end of the cooldown.
+ #
+ # The cooldown_duration is counted as part of the sleep_duration. So for
+ # the default values of 60 and 5, the service will cooldown for 5s, then wait
+ # for 55s.
+ #
+ # @return [Integer] the number of seconds to 'cooldown' for. This *must* be
+ # greater than zero, and less than sleep_duration
+ #
+ def cooldown_duration
+ 5
end
# The instance of INotify::Notifier that is holding our file watches.
#
# @return [INotify::Notifier]