In helping track down forem/forem#17041 I was looking at our cache busting logic. We were looking up a constant via the `.const_get` call from a string already defined inline. This refactor short-circuits naming a string, capitalizing it, then looking in the class's registered constants. There's also a subtle bug in the original; When `provider` equals "another_cache", the `#capitalize` method would return `"Another_cache"`, whereas `#classify` will return `"AnotherCache"`. Below are some benchmarks for the change. ```ruby require "benchmark" module EdgeCache class Bust def by_class Fastly end def by_const_get self.class.const_get("fastly".classify) end end end Benchmark.bmbm do |x| x.report("by_class") do 1000.times do EdgeCache::Bust.new.by_class end end x.report("by_const_get") do 1000.times do EdgeCache::Bust.new.by_const_get end end end ``` ```shell > bin/rails runner /Users/jfriesen/git/forem/bench.rb Rehearsal ------------------------------------------------ by_class 0.001239 0.000186 0.001425 ( 0.001342) by_const_get 0.011398 0.000136 0.011534 ( 0.011538) --------------------------------------- total: 0.012959sec user system total real by_class 0.000973 0.000030 0.001003 ( 0.000969) by_const_get 0.011102 0.000032 0.011134 ( 0.011104) ```
58 lines
1.6 KiB
Ruby
58 lines
1.6 KiB
Ruby
module EdgeCache
|
|
class Bust
|
|
def initialize
|
|
@provider_class = determine_provider_class
|
|
end
|
|
|
|
def self.call(*paths)
|
|
new.call(*paths)
|
|
end
|
|
|
|
def call(paths)
|
|
return unless @provider_class
|
|
|
|
paths = Array.wrap(paths)
|
|
paths.each do |path|
|
|
@provider_class.call(path)
|
|
rescue StandardError => e
|
|
Honeybadger.notify(e)
|
|
ForemStatsClient.increment(
|
|
"edgecache_bust.provider_error",
|
|
tags: ["provider_class:#{@provider_class}", "error_class:#{e.class}"],
|
|
)
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def determine_provider_class
|
|
return self.class::Fastly if fastly_enabled?
|
|
return self.class::Nginx if nginx_enabled_and_available?
|
|
|
|
nil
|
|
end
|
|
|
|
def fastly_enabled?
|
|
ApplicationConfig["FASTLY_API_KEY"].present? && ApplicationConfig["FASTLY_SERVICE_ID"].present?
|
|
end
|
|
|
|
def nginx_enabled_and_available?
|
|
return false if ApplicationConfig["OPENRESTY_URL"].blank?
|
|
|
|
uri = URI.parse(ApplicationConfig["OPENRESTY_URL"])
|
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
response = http.get(uri.request_uri)
|
|
|
|
return true if response.is_a?(Net::HTTPSuccess)
|
|
rescue StandardError => e
|
|
# If we can't connect to OpenResty, alert ourselves that it is
|
|
# unavailable and return false.
|
|
Rails.logger.error("Could not connect to OpenResty via #{ApplicationConfig['OPENRESTY_URL']}!")
|
|
Honeybadger.notify(e)
|
|
ForemStatsClient.increment("edgecache_bust.service_unavailable",
|
|
tags: ["path:#{ApplicationConfig['OPENRESTY_URL']}"])
|
|
end
|
|
|
|
false
|
|
end
|
|
end
|