18794: Don't restart if new config is unreadable or unchanged.
authorTom Clegg <tom@curii.com>
Tue, 26 Apr 2022 19:46:16 +0000 (15:46 -0400)
committerTom Clegg <tom@curii.com>
Tue, 26 Apr 2022 20:17:21 +0000 (16:17 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

services/api/config/initializers/reload_config.rb

index 6a7eac7a539833d470ec16f1161a705a6969129b..0698f92ca019bedae0d5b6898c6682e87e2c149d 100644 (file)
@@ -16,12 +16,34 @@ 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
+            continue
+          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
+            continue
+          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}")