diff options
author | James Lopez <james@jameslopez.es> | 2017-05-04 12:13:33 +0200 |
---|---|---|
committer | James Lopez <james@jameslopez.es> | 2017-05-04 12:13:33 +0200 |
commit | f81cf84035213002ce7931af6c3ffa917fe7fcbd (patch) | |
tree | 3393496e46cdacd5db03a2348dda8ed1a58a3d57 | |
parent | 2f7f1ce4e66db847414e2fc3de09556e75c51eb4 (diff) | |
download | gitlab-ce-f81cf84035213002ce7931af6c3ffa917fe7fcbd.tar.gz |
refactor worker into service
-rw-r--r-- | app/services/projects/propagate_service.rb | 47 | ||||
-rw-r--r-- | app/workers/propagate_project_service_worker.rb | 34 | ||||
-rw-r--r-- | spec/services/projects/propagate_service_spec.rb | 40 | ||||
-rw-r--r-- | spec/workers/propagate_project_service_worker_spec.rb | 52 |
4 files changed, 110 insertions, 63 deletions
diff --git a/app/services/projects/propagate_service.rb b/app/services/projects/propagate_service.rb new file mode 100644 index 00000000000..3c05dcce07c --- /dev/null +++ b/app/services/projects/propagate_service.rb @@ -0,0 +1,47 @@ +module Projects + class PropagateService + BATCH_SIZE = 100 + + def self.propagate!(*args) + new(*args).propagate! + end + + def initialize(template) + @template = template + end + + def propagate! + return unless @template&.active + + Rails.logger.info("Propagating services for template #{@template.id}") + + propagate_projects_with_template + end + + private + + def propagate_projects_with_template + offset = 0 + + loop do + batch = project_ids_batch(offset) + + batch.each { |project_id| create_from_template(project_id) } + + break if batch.count < BATCH_SIZE + + offset += BATCH_SIZE + end + end + + def create_from_template(project_id) + Service.build_from_template(project_id, @template).save! + end + + def project_ids_batch(offset) + Project.joins('LEFT JOIN services ON services.project_id = projects.id'). + where('services.type != ? OR services.id IS NULL', @template.type). + limit(BATCH_SIZE).offset(offset).pluck(:id) + end + end +end diff --git a/app/workers/propagate_project_service_worker.rb b/app/workers/propagate_project_service_worker.rb index 53551770968..ab2b7738f9a 100644 --- a/app/workers/propagate_project_service_worker.rb +++ b/app/workers/propagate_project_service_worker.rb @@ -3,44 +3,18 @@ class PropagateProjectServiceWorker include Sidekiq::Worker include DedicatedSidekiqQueue + sidekiq_options retry: 3 + LEASE_TIMEOUT = 30.minutes.to_i def perform(template_id) - template = Service.find_by(id: template_id) - - return unless template&.active - return unless try_obtain_lease_for(template.id) - - Rails.logger.info("Propagating services for template #{template.id}") + return unless try_obtain_lease_for(template_id) - project_ids_for_template(template) do |project_id| - Service.build_from_template(project_id, template).save! - end + Projects::PropagateService.propagate!(Service.find_by(id: template_id)) end private - def project_ids_for_template(template) - limit = 100 - offset = 0 - - loop do - batch = project_ids_batch(limit, offset, template.type) - - batch.each { |project_id| yield(project_id) } - - break if batch.count < limit - - offset += limit - end - end - - def project_ids_batch(limit, offset, template_type) - Project.joins('LEFT JOIN services ON services.project_id = projects.id'). - where('services.type != ? OR services.id IS NULL', template_type). - limit(limit).offset(offset).pluck(:id) - end - def try_obtain_lease_for(template_id) Gitlab::ExclusiveLease. new("propagate_project_service_worker:#{template_id}", timeout: LEASE_TIMEOUT). diff --git a/spec/services/projects/propagate_service_spec.rb b/spec/services/projects/propagate_service_spec.rb new file mode 100644 index 00000000000..ee40a7ecbab --- /dev/null +++ b/spec/services/projects/propagate_service_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe Projects::PropagateService, services: true do + describe '.propagate!' do + let!(:service_template) do + PushoverService.create( + template: true, + active: true, + properties: { + device: 'MyDevice', + sound: 'mic', + priority: 4, + user_key: 'asdf', + api_key: '123456789' + }) + end + + let!(:project) { create(:empty_project) } + + it 'creates services for projects' do + expect { described_class.propagate!(service_template) }. + to change { Service.count }.by(1) + end + + it 'does not create the service if it exists already' do + Service.build_from_template(project.id, service_template).save! + + expect { described_class.propagate!(service_template) }. + not_to change { Service.count } + end + + it 'creates the service containing the template attributes' do + described_class.propagate!(service_template) + + service = Service.find_by(type: service_template.type, template: false) + + expect(service.properties).to eq(service_template.properties) + end + end +end diff --git a/spec/workers/propagate_project_service_worker_spec.rb b/spec/workers/propagate_project_service_worker_spec.rb index d525a8b4a23..c16e95bd49b 100644 --- a/spec/workers/propagate_project_service_worker_spec.rb +++ b/spec/workers/propagate_project_service_worker_spec.rb @@ -1,43 +1,29 @@ require 'spec_helper' describe PropagateProjectServiceWorker do - describe '#perform' do - let!(:service_template) do - PushoverService.create( - template: true, - active: true, - properties: { - device: 'MyDevice', - sound: 'mic', - priority: 4, - user_key: 'asdf', - api_key: '123456789' - }) - end - - let!(:project) { create(:empty_project) } - - before do - allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:try_obtain). - and_return(true) - end - - it 'creates services for projects' do - expect { subject.perform(service_template.id) }.to change { Service.count }.by(1) - end + let!(:service_template) do + PushoverService.create( + template: true, + active: true, + properties: { + device: 'MyDevice', + sound: 'mic', + priority: 4, + user_key: 'asdf', + api_key: '123456789' + }) + end - it 'does not create the service if it exists already' do - Service.build_from_template(project.id, service_template).save! + before do + allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:try_obtain). + and_return(true) + end - expect { subject.perform(service_template.id) }.not_to change { Service.count } - end + describe '#perform' do + it 'calls the propagate service with the template' do + expect(Projects::PropagateService).to receive(:propagate!).with(service_template) - it 'creates the service containing the template attributes' do subject.perform(service_template.id) - - service = Service.find_by(type: service_template.type, template: false) - - expect(service.properties).to eq(service_template.properties) end end end |