Merge branch '13613-document-min-r-version'
[arvados.git] / services / api / lib / update_priority.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: AGPL-3.0
4
5 module UpdatePriority
6   extend CurrentApiClient
7
8   # Clean up after races.
9   #
10   # If container priority>0 but there are no committed container
11   # requests for it, reset priority to 0.
12   #
13   # If container priority=0 but there are committed container requests
14   # for it with priority>0, update priority.
15   def self.update_priority
16     if !File.owned?(Rails.root.join('tmp'))
17       Rails.logger.warn("UpdatePriority: not owner of #{Rails.root}/tmp, skipping")
18       return
19     end
20     lockfile = Rails.root.join('tmp', 'update_priority.lock')
21     File.open(lockfile, File::RDWR|File::CREAT, 0600) do |f|
22       return unless f.flock(File::LOCK_NB|File::LOCK_EX)
23
24       # priority>0 but should be 0:
25       ActiveRecord::Base.connection.
26         exec_query("UPDATE containers AS c SET priority=0 WHERE state IN ('Queued', 'Locked', 'Running') AND priority>0 AND uuid NOT IN (SELECT container_uuid FROM container_requests WHERE priority>0 AND state='Committed');", 'UpdatePriority')
27
28       # priority==0 but should be >0:
29       act_as_system_user do
30         Container.
31           joins("JOIN container_requests ON container_requests.container_uuid=containers.uuid AND container_requests.state=#{Container.sanitize(ContainerRequest::Committed)} AND container_requests.priority>0").
32           where('containers.state IN (?) AND containers.priority=0 AND container_requests.uuid IS NOT NULL',
33                 [Container::Queued, Container::Locked, Container::Running]).
34           map(&:update_priority!)
35       end
36     end
37   end
38
39   def self.run_update_thread
40     need = false
41     Rails.cache.fetch('UpdatePriority', expires_in: 5.seconds) do
42       need = true
43     end
44     return if !need
45
46     Thread.new do
47       Thread.current.abort_on_exception = false
48       begin
49         update_priority
50       rescue => e
51         Rails.logger.error "#{e.class}: #{e}\n#{e.backtrace.join("\n\t")}"
52       ensure
53         ActiveRecord::Base.connection.close
54       end
55     end
56   end
57 end