lib/caddy.rb in caddy-0.0.2 vs lib/caddy.rb in caddy-1.0.0

- old
+ new

@@ -1,81 +1,67 @@ # frozen_string_literal: true require "caddy/version" +require "caddy/task_observer" require "concurrent/timer_task" module Caddy class << self - attr_accessor :refresher, :refresher_error_handler - attr_writer :refresh_interval + attr_accessor :refresher, :error_handler, :refresh_interval end DEFAULT_REFRESH_INTERVAL = 60 REFRESH_INTERVAL_JITTER_PCT = 0.15 + @task = nil + @refresh_interval = DEFAULT_REFRESH_INTERVAL + @_started_pid = nil + def self.[](k) - raise "Please run `Caddy.start` before attempting to access values" unless @task - raise "Caddy variable access before initial load; allow some more time for your app to start up" unless @task.value - @task.value[k] + cache[k] end + def self.cache + raise "Please run `Caddy.start` before attempting to access the cache" unless @task + raise "Caddy cache access before initial load; allow some more time for your app to start up" unless @task.value + + @task.value + end + def self.start - unless refresher + unless refresher && refresher.respond_to?(:call) raise "Please set your cache refresher via `Caddy.refresher = -> { <code that returns a value> }`" end - jitter_amount = [1, refresh_interval * REFRESH_INTERVAL_JITTER_PCT].max + raise "`Caddy.refresh_interval` must be > 0" unless refresh_interval > 0 + + if @_started_pid && $$ != @_started_pid + raise "Please run `Caddy.start` *after* forking, as the refresh thread will get killed after fork" + end + + jitter_amount = [0.5, refresh_interval * REFRESH_INTERVAL_JITTER_PCT].max interval = refresh_interval + rand(-jitter_amount...jitter_amount) + timeout_interval = [interval - 1, 0.1].max - task = Concurrent::TimerTask.new( + stop # stop any existing task from running + + @task = Concurrent::TimerTask.new( run_now: true, execution_interval: interval, - timeout_interval: interval - 1) { refresher.call } + timeout_interval: timeout_interval + ) { refresher.call } - task.add_observer(InternalCaddyTaskObserver.new) - task.execute + @task.add_observer(Caddy::TaskObserver.new) + @task.execute - _stop_internal # stop any existing task from running + @_started_pid = $$ - @task = task # and transfer over the new task + @task.running? end def self.stop - raise "Please run `Caddy.start` before running `Caddy.stop`" unless @task - - _stop_internal - end - - def self.refresh_interval - @refresh_interval || DEFAULT_REFRESH_INTERVAL - end - - private_class_method def self._stop_internal @task.shutdown if @task && @task.running? end - class InternalCaddyTaskObserver - def update(time, _, boom) - return unless boom - - if Caddy.refresher_error_handler - if Caddy.refresher_error_handler.respond_to?(:call) - begin - Caddy.refresher_error_handler.call(boom) - rescue => incepted_boom - STDERR.puts "(#{time}) Caddy error handler itself errored: #{incepted_boom}" - end - else - # rubocop:disable Style/StringLiterals - STDERR.puts 'Caddy error handler not callable. Please set the error handler like:'\ - ' `Caddy.refresher_error_handler = -> (e) { puts "#{e}" }`' - # rubocop:enable Style/StringLiterals - - STDERR.puts "(#{time}) Caddy refresher failed with error #{boom}" - end - elsif boom.is_a?(Concurrent::TimeoutError) - STDERR.puts "(#{time}) Caddy refresher timed out" - else - STDERR.puts "(#{time}) Caddy refresher failed with error #{boom}" - end - end + def self.restart + stop || start end end