Skip to content
Snippets Groups Projects
Commit f81cf840 authored by James Lopez's avatar James Lopez
Browse files

refactor worker into service

parent 2f7f1ce4
No related branches found
No related tags found
No related merge requests found
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
Loading
Loading
@@ -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).
Loading
Loading
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
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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment