X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/1a3a8b0a7cc31e9bfb63c6001bc049a831e13dd1..e0f045ddedd05716bd813f801654308d3bbd2dd0:/services/api/config/initializers/reload_config.rb diff --git a/services/api/config/initializers/reload_config.rb b/services/api/config/initializers/reload_config.rb index af266cae36..b54e3bcf87 100644 --- a/services/api/config/initializers/reload_config.rb +++ b/services/api/config/initializers/reload_config.rb @@ -2,9 +2,10 @@ # # SPDX-License-Identifier: AGPL-3.0 -if !File.owned?(Rails.root.join('tmp')) - Rails.logger.debug("reload_config: not owner of #{Rails.root}/tmp, skipping") -else +# When updating this, please make the same changes in +# apps/workbench/config/initializers/reload_config.rb as well. + +def start_reload_thread Thread.new do lockfile = Rails.root.join('tmp', 'reload_config.lock') File.open(lockfile, File::WRONLY|File::CREAT, 0600) do |f| @@ -14,16 +15,45 @@ else # which could be a long time. Rails.logger.debug("reload_config: waiting for lock on #{lockfile}") f.flock(File::LOCK_EX) + + t_lastload = Rails.configuration.SourceTimestamp + hash_lastload = Rails.configuration.SourceSHA256 conffile = ENV['ARVADOS_CONFIG'] || "/etc/arvados/config.yml" - Rails.logger.info("reload_config: polling for updated mtime on #{conffile} with threshold #{Rails.configuration.SourceTimestamp}") + Rails.logger.info("reload_config: polling for updated mtime on #{conffile} with threshold #{t_lastload}") while true sleep 1 t = File.mtime(conffile) - if t.to_f > Rails.configuration.SourceTimestamp.to_f + # If the file is newer than 5s, re-read it even if the + # timestamp matches the previously loaded file. This enables + # us to detect changes even if the filesystem's timestamp + # precision cannot represent multiple updates per second. + if t.to_f != t_lastload.to_f || Time.now.to_f - t.to_f < 5 + Open3.popen2("arvados-server", "config-dump", "-skip-legacy") do |stdin, stdout, status_thread| + confs = YAML.load(stdout, deserialize_symbols: false) + hash = confs["SourceSHA256"] + rescue => e + Rails.logger.info("reload_config: config file updated but could not be loaded: #{e}") + t_lastload = t + next + end + if hash == hash_lastload + # If we reloaded a new or updated file, but the content is + # identical, keep polling instead of restarting. + t_lastload = t + next + end + restartfile = Rails.root.join('tmp', 'restart.txt') touchtime = Time.now Rails.logger.info("reload_config: mtime on #{conffile} changed to #{t}, touching #{restartfile} to #{touchtime}") - File.utime(touchtime, touchtime, restartfile) + begin + File.utime(touchtime, touchtime, restartfile) + rescue + # remove + re-create works even if the existing file is + # owned by root, provided the tempdir is writable. + File.unlink(restartfile) rescue nil + File.open(restartfile, 'w') {} + end # Even if passenger doesn't notice that we hit restart.txt # and kill our process, there's no point waiting around to # hit it again. @@ -33,3 +63,15 @@ else end end end + +if !File.owned?(Rails.root.join('tmp')) + Rails.logger.debug("reload_config: not owner of #{Rails.root}/tmp, skipping") +elsif ENV["ARVADOS_CONFIG"] == "none" + Rails.logger.debug("reload_config: no config in use, skipping") +elsif defined?(PhusionPassenger) + PhusionPassenger.on_event(:starting_worker_process) do |forked| + start_reload_thread + end +else + start_reload_thread +end