canvas-lms/config/initializers/cache_store.rb

109 lines
3.4 KiB
Ruby

# frozen_string_literal: true
#
# Copyright (C) 2015 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
last_cache_config = {}
cached_cache_config = Rails.root.join("config/cache_store.yml.cached")
load_cache_config = lambda do
raw_config = {}
first_try = true
begin
cache_map = {}
searched = Set.new
clusters_to_search = Switchman::DatabaseServer.all.map(&:id)
until clusters_to_search.empty?
cluster = clusters_to_search.shift
next if searched.include?(cluster)
searched << cluster
config = if first_try
raw_config[cluster] = Canvas.cache_store_config_for(cluster)
else
raw_config[cluster]
end
# link to another cluster
if config.is_a?(String)
clusters_to_search << config
cache_map[cluster] = config
next
end
unless config.present?
cache_map.delete(cluster)
next
end
last_cluster_cache_config = last_cache_config[cluster]
last_cache_config[cluster] = config
cache_map[cluster] = if last_cluster_cache_config == config
Switchman.config[:cache_map][cluster]
else
Canvas.lookup_cache_store(config, cluster)
end
end
cached_raw_config = cached_cache_config.read if cached_cache_config.exist?
yaml_raw_config = YAML.dump(raw_config)
begin
cached_cache_config.write(yaml_raw_config) if cached_raw_config != yaml_raw_config
rescue Errno::EACCES
# ignore permission errors
end
# resolve links
cache_map.each_key do |cluster_name|
value = cluster_name
while value.is_a?(String)
value = cache_map[value]
end
cache_map[cluster_name] = value
end
# fallback for no configuration whatsoever
cache_map[Rails.env] ||= ActiveSupport::Cache.lookup_store(:null_store)
Switchman::DatabaseServer.all.each do |db|
db.instance_variable_set(:@cache_store, nil)
end
Switchman.config[:cache_map] = cache_map
rescue Diplomat::KeyNotFound, Diplomat::UnknownStatus, Diplomat::PathNotFound => e
if first_try && cached_cache_config.exist?
warn "Failed to connect to Consul to read cache store config: #{e}"
# if we can't find consul, fall back to the cached config
raw_config = YAML.safe_load_file(cached_cache_config)
first_try = false
retry
end
raise
end
end
load_cache_config.call
Canvas::Reloader.on_reload(&load_cache_config)
ActiveSupport::Notifications.subscribe("cache_generate.active_support") do |_name, start, finish, _id, _options|
elapsed_time = finish - start
# used by Redis::Client#log_request_response added in lib/canvas/redis.rb
Thread.current[:last_cache_generate] = elapsed_time
end