Commit be0f6c42 authored by Tiago Botelho's avatar Tiago Botelho

raises error if another worker is already running and improves code quality

parent ebf5e945
...@@ -74,8 +74,7 @@ class RemoteMirror < ActiveRecord::Base ...@@ -74,8 +74,7 @@ class RemoteMirror < ActiveRecord::Base
end end
def sync def sync
return unless project return unless project && enabled
return if !enabled || update_in_progress?
schedule_update_job schedule_update_job
end end
......
class RepositoryUpdateRemoteMirrorWorker class RepositoryUpdateRemoteMirrorWorker
UpdateRemoteMirrorError = Class.new(StandardError) UpdateAlreadyInProgressError = Class.new(StandardError)
UpdateError = Class.new(StandardError)
include Sidekiq::Worker include Sidekiq::Worker
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
sidekiq_options queue: :project_mirror, retry: 3 sidekiq_options queue: :project_mirror, retry: 3
sidekiq_retries_exhausted do |msg, e| sidekiq_retry_in { |count| 30 * count }
sidekiq_retries_exhausted do |msg, _|
Sidekiq.logger.warn "Failed #{msg['class']} with #{msg['args']}: #{msg['error_message']}" Sidekiq.logger.warn "Failed #{msg['class']} with #{msg['args']}: #{msg['error_message']}"
end end
def perform(remote_mirror_id, scheduled_time) def perform(remote_mirror_id, scheduled_time)
begin
remote_mirror = RemoteMirror.find(remote_mirror_id) remote_mirror = RemoteMirror.find(remote_mirror_id)
return if remote_mirror.updated_since?(scheduled_time) return if remote_mirror.updated_since?(scheduled_time)
raise UpdateAlreadyInProgressError if remote_mirror.update_in_progress?
remote_mirror.update_start remote_mirror.update_start
project = remote_mirror.project project = remote_mirror.project
current_user = project.creator current_user = project.creator
result = Projects::UpdateRemoteMirrorService.new(project, current_user).execute(remote_mirror) result = Projects::UpdateRemoteMirrorService.new(project, current_user).execute(remote_mirror)
raise UpdateRemoteMirrorError, result[:message] if result[:status] == :error raise UpdateError, result[:message] if result[:status] == :error
remote_mirror.update_finish remote_mirror.update_finish
rescue UpdateRemoteMirrorError => ex rescue UpdateAlreadyInProgressError
raise
rescue UpdateError => ex
remote_mirror.mark_as_failed(Gitlab::UrlSanitizer.sanitize(ex.message)) remote_mirror.mark_as_failed(Gitlab::UrlSanitizer.sanitize(ex.message))
raise raise
rescue => ex rescue => ex
raise UpdateRemoteMirrorError, "#{ex.class}: #{ex.message}" raise UpdateError, "#{ex.class}: #{ex.message}"
end
end end
end end
...@@ -21,10 +21,11 @@ describe GitPushService, services: true do ...@@ -21,10 +21,11 @@ describe GitPushService, services: true do
let(:ref) { @ref } let(:ref) { @ref }
subject do subject do
described_class.new(project, user, oldrev: oldrev, newrev: newrev, ref: ref ) described_class.new(project, user, oldrev: oldrev, newrev: newrev, ref: ref)
end end
it 'fails stuck remote mirrors' do it 'fails stuck remote mirrors' do
allow(project).to receive(:update_remote_mirrors).and_return(project.remote_mirrors)
expect(project).to receive(:mark_stuck_remote_mirrors_as_failed!) expect(project).to receive(:mark_stuck_remote_mirrors_as_failed!)
subject.execute subject.execute
......
...@@ -11,7 +11,7 @@ describe RepositoryUpdateRemoteMirrorWorker do ...@@ -11,7 +11,7 @@ describe RepositoryUpdateRemoteMirrorWorker do
end end
describe '#perform' do describe '#perform' do
context 'with status scheduling' do context 'with status none' do
before do before do
remote_mirror.update_attributes(update_status: 'none') remote_mirror.update_attributes(update_status: 'none')
end end
...@@ -23,11 +23,13 @@ describe RepositoryUpdateRemoteMirrorWorker do ...@@ -23,11 +23,13 @@ describe RepositoryUpdateRemoteMirrorWorker do
end end
it 'sets status as failed when update remote mirror service executes with errors' do it 'sets status as failed when update remote mirror service executes with errors' do
expect_any_instance_of(Projects::UpdateRemoteMirrorService).to receive(:execute).with(remote_mirror).and_return(status: :error, message: 'fail!') error_message = 'fail!'
expect_any_instance_of(Projects::UpdateRemoteMirrorService).to receive(:execute).with(remote_mirror).and_return(status: :error, message: error_message)
expect do expect do
subject.perform(remote_mirror.id, Time.now) subject.perform(remote_mirror.id, Time.now)
end.to raise_error end.to raise_error(RepositoryUpdateRemoteMirrorWorker::UpdateError, 'fail!')
expect(remote_mirror.reload.update_status).to eq('failed') expect(remote_mirror.reload.update_status).to eq('failed')
end end
...@@ -41,6 +43,18 @@ describe RepositoryUpdateRemoteMirrorWorker do ...@@ -41,6 +43,18 @@ describe RepositoryUpdateRemoteMirrorWorker do
end end
end end
context 'with another worker already running' do
before do
remote_mirror.update_attributes(update_status: 'started')
end
it 'raises RemoteMirrorUpdateAlreadyInProgressError' do
expect do
subject.perform(remote_mirror.id, Time.now)
end.to raise_error(RepositoryUpdateRemoteMirrorWorker::UpdateAlreadyInProgressError)
end
end
context 'with status failed' do context 'with status failed' do
before do before do
remote_mirror.update_attributes(update_status: 'failed') remote_mirror.update_attributes(update_status: 'failed')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment