lib/caddy.rb in caddy-0.0.1 vs lib/caddy.rb in caddy-0.0.2
- old
+ new
@@ -1,66 +1,81 @@
+# frozen_string_literal: true
require "caddy/version"
require "concurrent/timer_task"
module Caddy
class << self
- attr_accessor :refresher
+ attr_accessor :refresher, :refresher_error_handler
attr_writer :refresh_interval
end
DEFAULT_REFRESH_INTERVAL = 60
- REFRESH_INTERVAL_JITTER_PCT = 0.1
- DEFAULT_INITIAL_VALUE_WAIT = 0.1
+ REFRESH_INTERVAL_JITTER_PCT = 0.15
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 system to warm up" unless @task.value
+ raise "Caddy variable access before initial load; allow some more time for your app to start up" unless @task.value
@task.value[k]
end
def self.start
unless refresher
raise "Please set your cache refresher via `Caddy.refresher = -> { <code that returns a value> }`"
end
- if @task
- puts "Caddy already running; shutting it down and starting over. Please ensure you run `Caddy.start`"\
- " only after fork/worker start in your web processes."
- @task.shutdown
- end
-
- jitter_amount = refresh_interval * REFRESH_INTERVAL_JITTER_PCT
+ jitter_amount = [1, refresh_interval * REFRESH_INTERVAL_JITTER_PCT].max
interval = refresh_interval + rand(-jitter_amount...jitter_amount)
- @task = Concurrent::TimerTask.new(
+ task = Concurrent::TimerTask.new(
run_now: true,
- freeze_on_deref: true,
execution_interval: interval,
timeout_interval: interval - 1) { refresher.call }
- @task.add_observer(CaddyTaskObserver.new)
- @task.execute
+ task.add_observer(InternalCaddyTaskObserver.new)
+ task.execute
+
+ _stop_internal # stop any existing task from running
+
+ @task = task # and transfer over the new task
end
def self.stop
raise "Please run `Caddy.start` before running `Caddy.stop`" unless @task
- @task.shutdown
- @task = nil
+ _stop_internal
end
def self.refresh_interval
@refresh_interval || DEFAULT_REFRESH_INTERVAL
end
- class CaddyTaskObserver
+ private_class_method def self._stop_internal
+ @task.shutdown if @task && @task.running?
+ end
+
+ class InternalCaddyTaskObserver
def update(time, _, boom)
return unless boom
- if boom.is_a?(Concurrent::TimeoutError)
- puts "(#{time}) Caddy refresher timed out"
+ 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
- puts "(#{time}) Caddy refresher failed with error #{boom}"
+ STDERR.puts "(#{time}) Caddy refresher failed with error #{boom}"
end
end
end
end