diff --git a/app/events/resync_event.rb b/app/events/resync_event.rb new file mode 100644 index 0000000000..9c5cb09553 --- /dev/null +++ b/app/events/resync_event.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class ResyncEvent < BaseEventStoreEvent + def self.create(provider_id:, service_id: nil) + zync = service_id ? { service_id: } : {} + + new( + metadata: { + provider_id:, + zync: + } + ) + end +end diff --git a/lib/tasks/zync.rake b/lib/tasks/zync.rake index e3bbe89374..c58121e9ed 100644 --- a/lib/tasks/zync.rake +++ b/lib/tasks/zync.rake @@ -1,44 +1,74 @@ # frozen_string_literal: true +BATCH_SIZE = 100 + namespace :zync do namespace :resync do - def each_with_progress(scope) + def each_with_progress(label, scope) + puts "== Resyncing #{label} ==" total_count = scope.count - batch_size = 100 index = 0 + step = [(total_count / 10), 1].max progress = -> do - break unless (index % batch_size) == 0 + break unless (index % step).zero? + percent = (index / total_count.to_f) * 100.0 puts "#{percent.round(2)}% completed" end - scope.find_each(batch_size: batch_size) do |object| + scope.find_each(batch_size: BATCH_SIZE) do |object| index += 1 yield object progress.call end end - desc 'Resync provider domains with zync' - task provider_domains: :environment do + def active_providers accounts = Account.providers_with_master if (provider_id = ENV["PROVIDER_ID"]) - accounts = accounts.where(id: provider_id) + accounts.where(id: provider_id) + else + accounts.without_suspended.without_deleted end - each_with_progress(accounts) { |account| Domains::ProviderDomainsChangedEvent.create_and_publish!(account) } + end + + def publish_zync_event(model, provider_id:, service_id: nil) + event = ResyncEvent.create(provider_id:, service_id:) + ZyncEvent.create_and_publish!(event, model) + end + + desc 'Resync provider domains with zync' + task providers: :environment do + each_with_progress('providers', active_providers) { |account| publish_zync_event(account, provider_id: account.id) } + end + + task provider_domains: :providers + + desc 'Resync services with zync' + task services: :environment do + services = Service.joins(:account).merge(active_providers) + each_with_progress('services', services) { |service| publish_zync_event(service, provider_id: service.account_id) } end desc 'Resync proxy domains with zync' - task proxy_domains: :environment do - services = Service.includes(:proxy) - if (provider_id = ENV["PROVIDER_ID"]) - services = services.where(account_id: provider_id) - end - each_with_progress(services) { |service| Domains::ProxyDomainsChangedEvent.create_and_publish!(service.proxy) } + task proxies: :environment do + proxies = Proxy.eager_load(service: :account).merge(active_providers) + each_with_progress('proxies', proxies) { |proxy| publish_zync_event(proxy, provider_id: proxy.service.account_id, service_id: proxy.service_id) } + end + + task proxy_domains: :proxies + + desc 'Resync applications with zync' + task applications: :environment do + cinstances = Cinstance.eager_load(service: :account).merge(active_providers) + each_with_progress('applications', cinstances) { |cinstance| publish_zync_event(cinstance, provider_id: cinstance.service.account_id, service_id: cinstance.service_id) } end desc 'Resync all domains with zync' - task domains: [:provider_domains, :proxy_domains] + task domains: %i[provider_domains proxy_domains] + + desc 'Full resync' + task full: %i[providers services proxies applications] end end diff --git a/test/unit/tasks/zync_test.rb b/test/unit/tasks/zync_test.rb index ce3cf00d58..43dc2bbd47 100644 --- a/test/unit/tasks/zync_test.rb +++ b/test/unit/tasks/zync_test.rb @@ -6,14 +6,90 @@ class ZyncTest < ActiveSupport::TestCase FactoryBot.create(:provider_account) end - test 'resync provider domains' do - Account.providers_with_master.each { |account| Domains::ProviderDomainsChangedEvent.expects(:create_and_publish!).with(account) } - execute_rake_task 'zync.rake', 'zync:resync:provider_domains' + class DomainsSyncTest < ZyncTest + test 'resync provider domains' do + active_providers.each { |account| ZyncEvent.expects(:create_and_publish!).with(instance_of(ResyncEvent), account) } + execute_rake_task 'zync.rake', 'zync:resync:provider_domains' + end + + test 'resync proxy domains' do + active_proxies.each { |proxy| ZyncEvent.expects(:create_and_publish!).with(instance_of(ResyncEvent), proxy) } + execute_rake_task 'zync.rake', 'zync:resync:proxy_domains' + end + + private + + def active_providers + Account.providers_with_master.without_suspended.without_deleted + end + + def active_proxies + Proxy.eager_load(service: :account).merge(active_providers) + end end - test 'resync proxy domains' do - Service.all.each { |service| Domains::ProxyDomainsChangedEvent.expects(:create_and_publish!).with(service.proxy) } - execute_rake_task 'zync.rake', 'zync:resync:proxy_domains' + class FullSyncTest < ZyncTest + setup do + @providers = FactoryBot.create_list(:provider_account, 3) + + @providers.each do |provider| + services = FactoryBot.create_list(:service, 2, account: provider) + services.each do |service| + plan = FactoryBot.create(:application_plan, issuer: service) + FactoryBot.create_list(:cinstance, 3, plan: plan, service: service) + end + end + end + + test 'full resync' do + load_collections + expect_resync_events + execute_rake_task 'zync.rake', 'zync:resync:full' + end + + test 'full resync excludes suspended providers' do + @providers.first.suspend! + load_collections + expect_resync_events + execute_rake_task 'zync.rake', 'zync:resync:full' + end + + test 'full resync excludes scheduled for deletion providers' do + @providers.first.schedule_for_deletion! + load_collections + expect_resync_events + execute_rake_task 'zync.rake', 'zync:resync:full' + end + + test 'full resync with PROVIDER_ID' do + ENV['PROVIDER_ID'] = @providers.first.id.to_s + load_collections + expect_resync_events + execute_rake_task 'zync.rake', 'zync:resync:full' + ensure + ENV.delete('PROVIDER_ID') + end + + private + + def load_collections + active = Account.providers_with_master + if (provider_id = ENV['PROVIDER_ID']) + active = active.where(id: provider_id) + else + active = active.without_suspended.without_deleted + end + @all_accounts = active.to_a + @all_services = Service.joins(:account).merge(active).to_a + @all_proxies = Proxy.eager_load(service: :account).merge(active).to_a + @all_cinstances = Cinstance.eager_load(service: :account).merge(active).to_a + end + + def expect_resync_events + (@all_accounts + @all_services + @all_proxies + @all_cinstances).each do |model| + ZyncEvent.expects(:create_and_publish!).with(instance_of(ResyncEvent), model) + end + end end end end