Repository Mirroring get stuck with import status: started state if invoked again within the worker lease timeout
When project.update mirror is invoked it sets import status to started
and then triggers RepositoryUpdateMirrorWorker to handle the job.
class Project < ActiveRecord::Base
...
def update_mirror(delay: 0)
return unless mirror? && repository_exists?
return if import_in_progress?
if import_failed?
import_retry
else
import_start
end
RepositoryUpdateMirrorWorker.perform_in(delay, self.id)
end
...
end
RepositoryUpdateMirrorWorker.perform is invoked and will immediatly return if it is unable to obtain a lease, causing the project to remain stuck in an import status: started
state.
class RepositoryUpdateMirrorWorker
...
def perform(project_id)
return unless try_obtain_lease(project_id)
@project = Project.find(project_id)
@current_user = @project.mirror_user || @project.creator
result = Projects::UpdateMirrorService.new(@project, @current_user).execute
if result[:status] == :error
project.mark_import_as_failed(result[:message])
return
end
project.import_finish
end
...
end
To resolve this issue the import state should be handled exclusively by the RepositoryUpdateMirrorWorker altogether by moving :
if import_failed?
import_retry
else
import_start
end
from project.update_mirror to RepositoryUpdateMirrorWorker.perform