From 9759288f3bf4d57b76327b9d7dc07ee0c4e27fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Sat, 24 Sep 2022 19:28:13 +0200 Subject: [PATCH] Run DB rake tasks on all tenants Some tasks don't have to run on every tenant. The task to calculate the TSV is only done for records which were present before we added the TSV column, and that isn't going to happen in any tenants because we added the TSV column before adding the tenants table. Similarly, the migration needed for existing polls isn't necessary because there weren't any tenants before we allowed to set the starting/ending time to polls. We aren't adding any tests for these tasks because tests for rake tasks are slow and tests creating tenants are also slow, making the combination of the two even slower, particularly if we add tests for every single task we're changing. We're adding tests for the `.run_on_each` method instead. --- app/models/tenant.rb | 6 ++++++ lib/tasks/files.rake | 8 +++++--- lib/tasks/settings.rake | 2 +- lib/tasks/stats.rake | 25 +++++++++++++++---------- lib/tasks/votes.rake | 9 ++++++--- spec/models/tenant_spec.rb | 21 +++++++++++++++++++++ 6 files changed, 54 insertions(+), 17 deletions(-) diff --git a/app/models/tenant.rb b/app/models/tenant.rb index dfc2c1d0c..6e82f3e9a 100644 --- a/app/models/tenant.rb +++ b/app/models/tenant.rb @@ -43,6 +43,12 @@ class Tenant < ApplicationRecord Apartment::Tenant.switch(...) end + def self.run_on_each(&block) + ["public"].union(Apartment.tenant_names).each do |schema| + switch(schema, &block) + end + end + private def create_schema diff --git a/lib/tasks/files.rake b/lib/tasks/files.rake index 978b5f4f1..929eaa951 100644 --- a/lib/tasks/files.rake +++ b/lib/tasks/files.rake @@ -1,8 +1,10 @@ namespace :files do desc "Removes cached attachments which weren't deleted for some reason" task remove_old_cached_attachments: :environment do - ActiveStorage::Blob.unattached - .where("active_storage_blobs.created_at <= ?", 1.day.ago) - .find_each(&:purge_later) + Tenant.run_on_each do + ActiveStorage::Blob.unattached + .where("active_storage_blobs.created_at <= ?", 1.day.ago) + .find_each(&:purge_later) + end end end diff --git a/lib/tasks/settings.rake b/lib/tasks/settings.rake index 11ac39c4b..f98aca240 100644 --- a/lib/tasks/settings.rake +++ b/lib/tasks/settings.rake @@ -2,7 +2,7 @@ namespace :settings do desc "Add new settings" task add_new_settings: :environment do ApplicationLogger.new.info "Adding new settings" - Setting.add_new_settings + Tenant.run_on_each { Setting.add_new_settings } end desc "Rename existing settings" diff --git a/lib/tasks/stats.rake b/lib/tasks/stats.rake index 66456a0b5..b7d397301 100644 --- a/lib/tasks/stats.rake +++ b/lib/tasks/stats.rake @@ -2,23 +2,28 @@ namespace :stats do desc "Generates stats which are not cached yet" task generate: :environment do ApplicationLogger.new.info "Updating budget and poll stats" - admin_ability = Ability.new(Administrator.first.user) - Budget.accessible_by(admin_ability, :read_stats).find_each do |budget| - Budget::Stats.new(budget).generate - print "." - end + Tenant.run_on_each do + admin_ability = Ability.new(Administrator.first.user) - Poll.accessible_by(admin_ability, :stats).find_each do |poll| - Poll::Stats.new(poll).generate - print "." + Budget.accessible_by(admin_ability, :read_stats).find_each do |budget| + Budget::Stats.new(budget).generate + print "." + end + + Poll.accessible_by(admin_ability, :stats).find_each do |poll| + Poll::Stats.new(poll).generate + print "." + end end end desc "Expires stats cache" task expire_cache: :environment do - [Budget, Poll].each do |model_class| - model_class.find_each { |record| record.find_or_create_stats_version.touch } + Tenant.run_on_each do + [Budget, Poll].each do |model_class| + model_class.find_each { |record| record.find_or_create_stats_version.touch } + end end end diff --git a/lib/tasks/votes.rake b/lib/tasks/votes.rake index 59e809cd9..d86bdb4c5 100644 --- a/lib/tasks/votes.rake +++ b/lib/tasks/votes.rake @@ -5,9 +5,12 @@ namespace :votes do models.each do |model| print "Updating votes hot_score for #{model}s" - model.find_each do |resource| - new_hot_score = resource.calculate_hot_score - resource.update_columns(hot_score: new_hot_score, updated_at: Time.current) + + Tenant.run_on_each do + model.find_each do |resource| + new_hot_score = resource.calculate_hot_score + resource.update_columns(hot_score: new_hot_score, updated_at: Time.current) + end end puts " ✅ " end diff --git a/spec/models/tenant_spec.rb b/spec/models/tenant_spec.rb index 5a7194eb7..c8b979023 100644 --- a/spec/models/tenant_spec.rb +++ b/spec/models/tenant_spec.rb @@ -133,6 +133,27 @@ describe Tenant do end end + describe ".run_on_each" do + it "runs the code on all tenants, including the default one" do + create(:tenant, schema: "andromeda") + create(:tenant, schema: "milky-way") + + Tenant.run_on_each do + Setting["org_name"] = "oh-my-#{Tenant.current_schema}" + end + + expect(Setting["org_name"]).to eq "oh-my-public" + + Tenant.switch("andromeda") do + expect(Setting["org_name"]).to eq "oh-my-andromeda" + end + + Tenant.switch("milky-way") do + expect(Setting["org_name"]).to eq "oh-my-milky-way" + end + end + end + describe "validations" do let(:tenant) { build(:tenant) }