Fix 2.4.2 upgrade notes formatting refs #19330
[arvados.git] / apps / workbench / config / initializers / reload_config.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: AGPL-3.0
4
5 # Please don't edit this version. Instead, edit
6 # services/api/config/initializers/reload_config.rb and update this
7 # copy. Or find a more reasonable way to share the code.
8
9 if !File.owned?(Rails.root.join('tmp'))
10   Rails.logger.debug("reload_config: not owner of #{Rails.root}/tmp, skipping")
11 elsif ENV["ARVADOS_CONFIG"] == "none"
12   Rails.logger.debug("reload_config: no config in use, skipping")
13 else
14   Thread.new do
15     lockfile = Rails.root.join('tmp', 'reload_config.lock')
16     File.open(lockfile, File::WRONLY|File::CREAT, 0600) do |f|
17       # Note we don't use LOCK_NB here. If we did, each time passenger
18       # kills the lock-holder process, we would be left with nobody
19       # checking for updates until passenger starts a new worker,
20       # which could be a long time.
21       Rails.logger.debug("reload_config: waiting for lock on #{lockfile}")
22       f.flock(File::LOCK_EX)
23
24       t_lastload = Rails.configuration.SourceTimestamp
25       hash_lastload = Rails.configuration.SourceSHA256
26       conffile = ENV['ARVADOS_CONFIG'] || "/etc/arvados/config.yml"
27       Rails.logger.info("reload_config: polling for updated mtime on #{conffile} with threshold #{t_lastload}")
28       while true
29         sleep 1
30         t = File.mtime(conffile)
31         # If the file is newer than 5s, re-read it even if the
32         # timestamp matches the previously loaded file. This enables
33         # us to detect changes even if the filesystem's timestamp
34         # precision cannot represent multiple updates per second.
35         if t.to_f != t_lastload.to_f || Time.now.to_f - t.to_f < 5
36           Open3.popen2("arvados-server", "config-dump", "-skip-legacy") do |stdin, stdout, status_thread|
37             confs = YAML.load(stdout, deserialize_symbols: false)
38             hash = confs["SourceSHA256"]
39           rescue => e
40             Rails.logger.info("reload_config: config file updated but could not be loaded: #{e}")
41             t_lastload = t
42             continue
43           end
44           if hash == hash_lastload
45             # If we reloaded a new or updated file, but the content is
46             # identical, keep polling instead of restarting.
47             t_lastload = t
48             continue
49           end
50
51           restartfile = Rails.root.join('tmp', 'restart.txt')
52           touchtime = Time.now
53           Rails.logger.info("reload_config: mtime on #{conffile} changed to #{t}, touching #{restartfile} to #{touchtime}")
54           begin
55             File.utime(touchtime, touchtime, restartfile)
56           rescue
57             # remove + re-create works even if the existing file is
58             # owned by root, provided the tempdir is writable.
59             File.unlink(restartfile) rescue nil
60             File.open(restartfile, 'w') {}
61           end
62           # Even if passenger doesn't notice that we hit restart.txt
63           # and kill our process, there's no point waiting around to
64           # hit it again.
65           break
66         end
67       end
68     end
69   end
70 end