14259: Collection class copies remote blocks when saving.
[arvados.git] / services / api / lib / sweep_trashed_objects.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: AGPL-3.0
4
5 require 'current_api_client'
6
7 module SweepTrashedObjects
8   extend CurrentApiClient
9
10   def self.delete_project_and_contents(p_uuid)
11     p = Group.find_by_uuid(p_uuid)
12     if !p || p.group_class != 'project'
13       raise "can't sweep group '#{p_uuid}', it may not exist or not be a project"
14     end
15     # First delete sub projects
16     Group.where({group_class: 'project', owner_uuid: p_uuid}).each do |sub_project|
17       delete_project_and_contents(sub_project.uuid)
18     end
19     # Next, iterate over all tables which have owner_uuid fields, with some
20     # exceptions, and delete records owned by this project
21     skipped_classes = ['Group', 'User']
22     ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |klass|
23       if !skipped_classes.include?(klass.name) && klass.columns.collect(&:name).include?('owner_uuid')
24         klass.where({owner_uuid: p_uuid}).destroy_all
25       end
26     end
27     # Finally delete the project itself
28     p.destroy
29   end
30
31   def self.sweep_now
32     act_as_system_user do
33       # Sweep trashed collections
34       Collection.
35         where('delete_at is not null and delete_at < statement_timestamp()').
36         destroy_all
37       Collection.
38         where('is_trashed = false and trash_at < statement_timestamp()').
39         update_all('is_trashed = true')
40
41       # Sweep trashed projects and their contents
42       Group.
43         where({group_class: 'project'}).
44         where('delete_at is not null and delete_at < statement_timestamp()').each do |project|
45           delete_project_and_contents(project.uuid)
46       end
47       Group.
48         where({group_class: 'project'}).
49         where('is_trashed = false and trash_at < statement_timestamp()').
50         update_all('is_trashed = true')
51     end
52   end
53
54   def self.sweep_if_stale
55     return if Rails.configuration.trash_sweep_interval <= 0
56     exp = Rails.configuration.trash_sweep_interval.seconds
57     need = false
58     Rails.cache.fetch('SweepTrashedObjects', expires_in: exp) do
59       need = true
60     end
61     if need
62       Thread.new do
63         Thread.current.abort_on_exception = false
64         begin
65           sweep_now
66         rescue => e
67           Rails.logger.error "#{e.class}: #{e}\n#{e.backtrace.join("\n\t")}"
68         ensure
69           ActiveRecord::Base.connection.close
70         end
71       end
72     end
73   end
74 end