diff --git a/.rubocop_todo/style/arguments_forwarding.yml b/.rubocop_todo/style/arguments_forwarding.yml index b72751ed27946b00ed526d2c6fb7b86833d5a29c..53ae5e4a96c71ddecceb9957b45c2f7dc0efc4a6 100644 --- a/.rubocop_todo/style/arguments_forwarding.yml +++ b/.rubocop_todo/style/arguments_forwarding.yml @@ -47,7 +47,6 @@ Style/ArgumentsForwarding: - 'app/workers/concerns/limited_capacity/worker.rb' - 'app/workers/concerns/reactive_cacheable_worker.rb' - 'app/workers/concerns/reenqueuer.rb' - - 'app/workers/gitlab/github_import/refresh_import_jid_worker.rb' - 'app/workers/pages_worker.rb' - 'config/initializers/6_labkit_middleware.rb' - 'config/initializers/active_record_table_definition.rb' diff --git a/.rubocop_todo/style/guard_clause.yml b/.rubocop_todo/style/guard_clause.yml index 9896356b1f603d77301705b4a92c2b5132df3fb5..3ff511a25b76c674c7ec4106728146880b8f54c1 100644 --- a/.rubocop_todo/style/guard_clause.yml +++ b/.rubocop_todo/style/guard_clause.yml @@ -234,7 +234,6 @@ Style/GuardClause: - 'app/workers/container_registry/migration/guard_worker.rb' - 'app/workers/deployments/hooks_worker.rb' - 'app/workers/deployments/link_merge_request_worker.rb' - - 'app/workers/gitlab/github_import/refresh_import_jid_worker.rb' - 'app/workers/google_cloud/create_cloudsql_instance_worker.rb' - 'app/workers/packages/cleanup/execute_policy_worker.rb' - 'app/workers/packages/maven/metadata/sync_worker.rb' diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index 269fac4151dd4fb6c85aa3ca8c1a0b49eb727fc7..1413638e903dbd2c6059b509dcf70fab1fcdaf8d 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -3198,6 +3198,15 @@ :weight: 2 :idempotent: true :tags: [] +- :name: import_refresh_import_jid + :worker_name: Gitlab::Import::RefreshImportJidWorker + :feature_category: :importers + :has_external_dependencies: false + :urgency: :low + :resource_boundary: :unknown + :weight: 1 + :idempotent: true + :tags: [] - :name: incident_management_close_incident :worker_name: IncidentManagement::CloseIncidentWorker :feature_category: :incident_management diff --git a/app/workers/concerns/gitlab/bitbucket_import/stage_methods.rb b/app/workers/concerns/gitlab/bitbucket_import/stage_methods.rb index 51e2f5cff227dfbee7847999a6ffb00866638b65..3af4f24438aff0375c39550d81db95aaa88b491f 100644 --- a/app/workers/concerns/gitlab/bitbucket_import/stage_methods.rb +++ b/app/workers/concerns/gitlab/bitbucket_import/stage_methods.rb @@ -16,6 +16,8 @@ module StageMethods sidekiq_options dead: false, retry: 6 + sidekiq_options status_expiration: Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION + sidekiq_retries_exhausted do |msg, e| Gitlab::Import::ImportFailureService.track( project_id: msg['args'][0], @@ -33,6 +35,8 @@ def perform(project_id) return unless project + Import::RefreshImportJidWorker.perform_in_the_future(project_id, jid) + import(project) info(project_id, message: 'stage finished') diff --git a/app/workers/concerns/gitlab/bitbucket_server_import/stage_methods.rb b/app/workers/concerns/gitlab/bitbucket_server_import/stage_methods.rb index cf5710e6108c3e9b4335cfa8381274a9434c6b41..304547ac1cc358acb6d9f047b4a3ad895ad66d00 100644 --- a/app/workers/concerns/gitlab/bitbucket_server_import/stage_methods.rb +++ b/app/workers/concerns/gitlab/bitbucket_server_import/stage_methods.rb @@ -16,6 +16,8 @@ module StageMethods sidekiq_options dead: false, retry: 6 + sidekiq_options status_expiration: Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION + sidekiq_retries_exhausted do |msg, e| Gitlab::Import::ImportFailureService.track( project_id: msg['args'][0], @@ -31,6 +33,8 @@ def perform(project_id) return unless (project = find_project(project_id)) + Import::RefreshImportJidWorker.perform_in_the_future(project_id, jid) + import(project) info(project_id, message: 'stage finished') diff --git a/app/workers/concerns/gitlab/github_import/stage_methods.rb b/app/workers/concerns/gitlab/github_import/stage_methods.rb index 69cf6f424af02ffd46776a8df7fe70989a0a9bdc..f6a46f50ca388c94bd10f769e149ceade8c0c638 100644 --- a/app/workers/concerns/gitlab/github_import/stage_methods.rb +++ b/app/workers/concerns/gitlab/github_import/stage_methods.rb @@ -62,7 +62,7 @@ def perform(project_id) return end - RefreshImportJidWorker.perform_in_the_future(project.id, jid) + Import::RefreshImportJidWorker.perform_in_the_future(project.id, jid) client = GithubImport.new_client_for(project) diff --git a/app/workers/gitlab/bitbucket_import/stage/import_issues_notes_worker.rb b/app/workers/gitlab/bitbucket_import/stage/import_issues_notes_worker.rb index cbd67099086a816871ed60b924f168f95f561c49..af7927b80a8194d0444037b8e843b62f2091ae35 100644 --- a/app/workers/gitlab/bitbucket_import/stage/import_issues_notes_worker.rb +++ b/app/workers/gitlab/bitbucket_import/stage/import_issues_notes_worker.rb @@ -12,8 +12,6 @@ class ImportIssuesNotesWorker # rubocop:disable Scalability/IdempotentWorker def import(project) waiter = importer_class.new(project).execute - project.import_state.refresh_jid_expiration - AdvanceStageWorker.perform_async( project.id, { waiter.key => waiter.jobs_remaining }, diff --git a/app/workers/gitlab/bitbucket_import/stage/import_issues_worker.rb b/app/workers/gitlab/bitbucket_import/stage/import_issues_worker.rb index 31a11d802c73730599cdf0ad971effa01dd5c26a..d2dac824e8139018a59a1049292a88caa273d9ad 100644 --- a/app/workers/gitlab/bitbucket_import/stage/import_issues_worker.rb +++ b/app/workers/gitlab/bitbucket_import/stage/import_issues_worker.rb @@ -12,8 +12,6 @@ class ImportIssuesWorker # rubocop:disable Scalability/IdempotentWorker def import(project) waiter = importer_class.new(project).execute - project.import_state.refresh_jid_expiration - AdvanceStageWorker.perform_async( project.id, { waiter.key => waiter.jobs_remaining }, diff --git a/app/workers/gitlab/bitbucket_import/stage/import_lfs_objects_worker.rb b/app/workers/gitlab/bitbucket_import/stage/import_lfs_objects_worker.rb index c88a1be34466be7280327bae8457531a96958ff8..328a66dcdca9e64f27b9c87efd52a8d967eba8df 100644 --- a/app/workers/gitlab/bitbucket_import/stage/import_lfs_objects_worker.rb +++ b/app/workers/gitlab/bitbucket_import/stage/import_lfs_objects_worker.rb @@ -12,8 +12,6 @@ class ImportLfsObjectsWorker # rubocop:disable Scalability/IdempotentWorker def import(project) waiter = importer_class.new(project).execute - project.import_state.refresh_jid_expiration - AdvanceStageWorker.perform_async( project.id, { waiter.key => waiter.jobs_remaining }, diff --git a/app/workers/gitlab/bitbucket_import/stage/import_pull_requests_notes_worker.rb b/app/workers/gitlab/bitbucket_import/stage/import_pull_requests_notes_worker.rb index 36d60c7246c583173dfd6e0a7d82aa272902a3cd..fcabe80abc49d04abd711f3259c70dae4d0a46ef 100644 --- a/app/workers/gitlab/bitbucket_import/stage/import_pull_requests_notes_worker.rb +++ b/app/workers/gitlab/bitbucket_import/stage/import_pull_requests_notes_worker.rb @@ -12,8 +12,6 @@ class ImportPullRequestsNotesWorker # rubocop:disable Scalability/IdempotentWork def import(project) waiter = importer_class.new(project).execute - project.import_state.refresh_jid_expiration - AdvanceStageWorker.perform_async( project.id, { waiter.key => waiter.jobs_remaining }, diff --git a/app/workers/gitlab/bitbucket_import/stage/import_pull_requests_worker.rb b/app/workers/gitlab/bitbucket_import/stage/import_pull_requests_worker.rb index 3f85c832d50983cb855503917d542d84bd648d85..373dfcdb1f78781a1ac1886cc64f881c4f29ea63 100644 --- a/app/workers/gitlab/bitbucket_import/stage/import_pull_requests_worker.rb +++ b/app/workers/gitlab/bitbucket_import/stage/import_pull_requests_worker.rb @@ -12,8 +12,6 @@ class ImportPullRequestsWorker # rubocop:disable Scalability/IdempotentWorker def import(project) waiter = importer_class.new(project).execute - project.import_state.refresh_jid_expiration - AdvanceStageWorker.perform_async( project.id, { waiter.key => waiter.jobs_remaining }, diff --git a/app/workers/gitlab/bitbucket_server_import/stage/import_lfs_objects_worker.rb b/app/workers/gitlab/bitbucket_server_import/stage/import_lfs_objects_worker.rb index 1002047225c93fd997497fd2f12949fed5675e1f..020205dcddbe997a1145d0d3dd2a2f49c941d04c 100644 --- a/app/workers/gitlab/bitbucket_server_import/stage/import_lfs_objects_worker.rb +++ b/app/workers/gitlab/bitbucket_server_import/stage/import_lfs_objects_worker.rb @@ -12,8 +12,6 @@ class ImportLfsObjectsWorker # rubocop:disable Scalability/IdempotentWorker def import(project) waiter = importer_class.new(project).execute - project.import_state.refresh_jid_expiration - AdvanceStageWorker.perform_async( project.id, { waiter.key => waiter.jobs_remaining }, diff --git a/app/workers/gitlab/bitbucket_server_import/stage/import_notes_worker.rb b/app/workers/gitlab/bitbucket_server_import/stage/import_notes_worker.rb index b30f93058298a2ae1a561d34c33b344e4405e69e..8020dc7ab3af9b8a759847c714c8d6599da24d10 100644 --- a/app/workers/gitlab/bitbucket_server_import/stage/import_notes_worker.rb +++ b/app/workers/gitlab/bitbucket_server_import/stage/import_notes_worker.rb @@ -12,8 +12,6 @@ class ImportNotesWorker # rubocop:disable Scalability/IdempotentWorker def import(project) waiter = importer_class.new(project).execute - project.import_state.refresh_jid_expiration - AdvanceStageWorker.perform_async( project.id, { waiter.key => waiter.jobs_remaining }, diff --git a/app/workers/gitlab/bitbucket_server_import/stage/import_pull_requests_worker.rb b/app/workers/gitlab/bitbucket_server_import/stage/import_pull_requests_worker.rb index 9e3d570e20dfb79e9da45c0ab2a24ebdfe049de4..c39665b68296543482a3b00d15a1e08740086a6e 100644 --- a/app/workers/gitlab/bitbucket_server_import/stage/import_pull_requests_worker.rb +++ b/app/workers/gitlab/bitbucket_server_import/stage/import_pull_requests_worker.rb @@ -12,8 +12,6 @@ class ImportPullRequestsWorker # rubocop:disable Scalability/IdempotentWorker def import(project) waiter = importer_class.new(project).execute - project.import_state.refresh_jid_expiration - AdvanceStageWorker.perform_async( project.id, { waiter.key => waiter.jobs_remaining }, diff --git a/app/workers/gitlab/github_import/refresh_import_jid_worker.rb b/app/workers/gitlab/github_import/refresh_import_jid_worker.rb index dfc581f201b69f92075c87c5637acc112ce0c844..ee7e45889bd841fb54cd618948299717e690ae0e 100644 --- a/app/workers/gitlab/github_import/refresh_import_jid_worker.rb +++ b/app/workers/gitlab/github_import/refresh_import_jid_worker.rb @@ -9,42 +9,11 @@ class RefreshImportJidWorker # rubocop:disable Scalability/IdempotentWorker include GithubImport::Queue - sidekiq_options retry: 5 - - # The interval to schedule new instances of this job at. - INTERVAL = 5.minutes.to_i - def self.perform_in_the_future(*args) - perform_in(INTERVAL, *args) - end - - # project_id - The ID of the project that is being imported. - # check_job_id - The ID of the job for which to check the status. - def perform(project_id, check_job_id) - import_state = find_import_state(project_id) - return unless import_state - - if SidekiqStatus.running?(check_job_id) - # As long as the worker is running we want to keep refreshing - # the worker's JID as well as the import's JID. - Gitlab::SidekiqStatus.expire(check_job_id, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION) - Gitlab::SidekiqStatus.set(import_state.jid, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION) - - self.class.perform_in_the_future(project_id, check_job_id) - end - - # If the job is no longer running there's nothing else we need to do. If - # the clone job completed successfully it will have scheduled the next - # stage, if it died there's nothing we can do anyway. - end - - # rubocop: disable CodeReuse/ActiveRecord - def find_import_state(project_id) - ProjectImportState.select(:jid) - .with_status(:started) - .find_by(project_id: project_id) + # Delegate to new version of this job so stale sidekiq nodes can still + # run instead of no-op + Gitlab::Import::RefreshImportJidWorker.perform_in_the_future(*args) end - # rubocop: enable CodeReuse/ActiveRecord end end end diff --git a/app/workers/gitlab/import/refresh_import_jid_worker.rb b/app/workers/gitlab/import/refresh_import_jid_worker.rb new file mode 100644 index 0000000000000000000000000000000000000000..f9a7bf870afcb6911539bbb11054a145dac28397 --- /dev/null +++ b/app/workers/gitlab/import/refresh_import_jid_worker.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module Gitlab + module Import + class RefreshImportJidWorker + include ApplicationWorker + + data_consistency :delayed + idempotent! + + feature_category :importers + sidekiq_options dead: false + + sidekiq_options retry: 5 + + # The interval to schedule new instances of this job at. + INTERVAL = 5.minutes.to_i + + def self.perform_in_the_future(*args) + perform_in(INTERVAL, *args) + end + + # project_id - The ID of the project that is being imported. + # check_job_id - The ID of the job for which to check the status. + # params - to avoid multiple releases if parameters change + def perform(project_id, check_job_id, _params = {}) + return unless SidekiqStatus.running?(check_job_id) + + import_state_jid = ProjectImportState.jid_by(project_id: project_id, status: :started)&.jid + return unless import_state_jid + + # As long as the worker is running we want to keep refreshing + # the worker's JID as well as the import's JID. + Gitlab::SidekiqStatus.expire(check_job_id, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION) + Gitlab::SidekiqStatus.set(import_state_jid, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION) + + self.class.perform_in_the_future(project_id, check_job_id) + end + end + end +end diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml index 994cdb7d67aeeb316bdefd29019195a4861d18eb..a7182e334180c67941d677461929b10acacf33cf 100644 --- a/config/sidekiq_queues.yml +++ b/config/sidekiq_queues.yml @@ -373,6 +373,8 @@ - 1 - - import_issues_csv - 2 +- - import_refresh_import_jid + - 1 - - incident_management - 2 - - incident_management_apply_incident_sla_exceeded_label diff --git a/lib/gitlab/github_import/parallel_importer.rb b/lib/gitlab/github_import/parallel_importer.rb index a71590c02f82e89c941be2c94d56c82d2989c93d..e045c424fe1bb995999f37e5c25219e1d51fb505 100644 --- a/lib/gitlab/github_import/parallel_importer.rb +++ b/lib/gitlab/github_import/parallel_importer.rb @@ -35,7 +35,7 @@ def initialize(project) def execute Gitlab::Import::SetAsyncJid.set_jid(project.import_state) - # We need to track this job's status for use by Gitlab::GithubImport::RefreshImportJidWorker. + # We need to track this job's status for use by Gitlab::Import::RefreshImportJidWorker. Stage::ImportRepositoryWorker .with_status .perform_async(project.id) diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml index 22d8871b71877a83cc26c1d27764b4cbb5872210..9e1038b4d4edd25128f2590ebc2bce29334679b7 100644 --- a/spec/support/rspec_order_todo.yml +++ b/spec/support/rspec_order_todo.yml @@ -9489,7 +9489,6 @@ - './spec/workers/gitlab/github_import/import_issue_worker_spec.rb' - './spec/workers/gitlab/github_import/import_note_worker_spec.rb' - './spec/workers/gitlab/github_import/import_pull_request_worker_spec.rb' -- './spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb' - './spec/workers/gitlab/github_import/stage/finish_import_worker_spec.rb' - './spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb' - './spec/workers/gitlab/github_import/stage/import_issue_events_worker_spec.rb' diff --git a/spec/support/shared_examples/lib/gitlab/bitbucket_import/stage_methods_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/bitbucket_import/stage_methods_shared_examples.rb index f128aa92a5317758ace22d11fd24c703f0ba6f85..46771afaa3422d88b7bc2a5a7ecc838281624ece 100644 --- a/spec/support/shared_examples/lib/gitlab/bitbucket_import/stage_methods_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/bitbucket_import/stage_methods_shared_examples.rb @@ -16,7 +16,7 @@ end end - describe '.perform' do + describe '#perform' do let(:worker) { described_class.new } it 'executes the import' do @@ -25,5 +25,16 @@ worker.perform(project.id) end + + it 'queues RefreshImportJidWorker' do + allow(worker).to receive(:import) + allow(worker).to receive(:jid).and_return('mock_jid') + + expect(Gitlab::Import::RefreshImportJidWorker) + .to receive(:perform_in_the_future) + .with(project.id, 'mock_jid') + + worker.perform(project.id) + end end end diff --git a/spec/support/shared_examples/lib/gitlab/bitbucket_server_import/stage_methods_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/bitbucket_server_import/stage_methods_shared_examples.rb index 1246dd2979b9cf4685e9f92751f89bbf7511627e..c73c9f6028228f52438890d3180502ff9fef4fcc 100644 --- a/spec/support/shared_examples/lib/gitlab/bitbucket_server_import/stage_methods_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/bitbucket_server_import/stage_methods_shared_examples.rb @@ -15,4 +15,26 @@ described_class.sidekiq_retries_exhausted_block.call(job, StandardError.new) end end + + describe '#perform' do + let(:worker) { described_class.new } + + it 'executes the import' do + expect(worker).to receive(:import).with(project).once + expect(Gitlab::BitbucketServerImport::Logger).to receive(:info).twice + + worker.perform(project.id) + end + + it 'queues RefreshImportJidWorker' do + allow(worker).to receive(:import) + allow(worker).to receive(:jid).and_return('mock_jid') + + expect(Gitlab::Import::RefreshImportJidWorker) + .to receive(:perform_in_the_future) + .with(project.id, 'mock_jid') + + worker.perform(project.id) + end + end end diff --git a/spec/support/shared_examples/workers/gitlab/github_import/stage_methods_shared_examples.rb b/spec/support/shared_examples/workers/gitlab/github_import/stage_methods_shared_examples.rb index b5e3589d86c50c05f71dc4fa27569451a050a9a1..6d064e0c999d34df7488026266bb5bba7222119a 100644 --- a/spec/support/shared_examples/workers/gitlab/github_import/stage_methods_shared_examples.rb +++ b/spec/support/shared_examples/workers/gitlab/github_import/stage_methods_shared_examples.rb @@ -100,7 +100,7 @@ allow(worker).to receive(:import) allow(worker).to receive(:jid).and_return('mock_jid') - expect(Gitlab::GithubImport::RefreshImportJidWorker) + expect(Gitlab::Import::RefreshImportJidWorker) .to receive(:perform_in_the_future) .with(project.id, 'mock_jid') diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb index 75101c1a24e4862510ce5cafafaf4007405ae731..dc2851bd562eb8a83915ac7e8e6c643fefdf183e 100644 --- a/spec/workers/every_sidekiq_worker_spec.rb +++ b/spec/workers/every_sidekiq_worker_spec.rb @@ -279,7 +279,6 @@ 'Gitlab::GithubImport::PullRequests::ImportReviewWorker' => 5, 'Gitlab::GithubImport::PullRequests::ImportMergedByWorker' => 5, 'Gitlab::GithubImport::ImportPullRequestWorker' => 5, - 'Gitlab::GithubImport::RefreshImportJidWorker' => 5, 'Gitlab::GithubImport::ReplayEventsWorker' => 5, 'Gitlab::GithubImport::Stage::FinishImportWorker' => 6, 'Gitlab::GithubImport::Stage::ImportBaseDataWorker' => 6, @@ -298,6 +297,7 @@ 'Gitlab::GithubGistsImport::ImportGistWorker' => 5, 'Gitlab::GithubGistsImport::StartImportWorker' => 5, 'Gitlab::GithubGistsImport::FinishImportWorker' => 5, + 'Gitlab::Import::RefreshImportJidWorker' => 5, 'Gitlab::JiraImport::AdvanceStageWorker' => 6, 'Gitlab::JiraImport::ImportIssueWorker' => 5, 'Gitlab::JiraImport::Stage::FinishImportWorker' => 6, diff --git a/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb b/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb index 5d0cb05c8d5ed755261f88e024d570071c78642d..70f958b60f6a1fd7e08a4d333d20f41d710147cf 100644 --- a/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb +++ b/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb @@ -6,102 +6,12 @@ let(:worker) { described_class.new } describe '.perform_in_the_future' do - it 'schedules a job in the future' do - expect(described_class) - .to receive(:perform_in) - .with(5.minutes.to_i, 10, '123') + it 'calls Gitlab::Import::RefreshImportJidWorker#perform_in_the_future' do + expect(Gitlab::Import::RefreshImportJidWorker) + .to receive(:perform_in_the_future) + .with(10, '123') described_class.perform_in_the_future(10, '123') end end - - describe '#perform' do - let(:project) { create(:project) } - let(:import_state) { create(:import_state, project: project, jid: '123abc') } - - context 'when the project does not exist' do - it 'does nothing' do - expect(Gitlab::SidekiqStatus) - .not_to receive(:running?) - - worker.perform(-1, '123') - end - end - - context 'when the job is running' do - it 'refreshes the import JID and reschedules itself' do - allow(worker) - .to receive(:find_import_state) - .with(project.id) - .and_return(import_state) - - expect(Gitlab::SidekiqStatus) - .to receive(:running?) - .with('123') - .and_return(true) - - expect(Gitlab::SidekiqStatus) - .to receive(:expire) - .with('123', Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION) - - expect(Gitlab::SidekiqStatus) - .to receive(:set) - .with(import_state.jid, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION) - - expect(worker.class) - .to receive(:perform_in_the_future) - .with(project.id, '123') - - worker.perform(project.id, '123') - end - end - - context 'when the job is no longer running' do - it 'returns' do - allow(worker) - .to receive(:find_import_state) - .with(project.id) - .and_return(project) - - expect(Gitlab::SidekiqStatus) - .to receive(:running?) - .with('123') - .and_return(false) - - expect(Gitlab::SidekiqStatus) - .not_to receive(:expire) - - expect(Gitlab::SidekiqStatus) - .not_to receive(:set) - - worker.perform(project.id, '123') - end - end - end - - describe '#find_import_state' do - it 'returns a ProjectImportState' do - project = create(:project, :import_started) - - expect(worker.find_import_state(project.id)).to be_an_instance_of(ProjectImportState) - end - - # it 'only selects the import JID field' do - # project = create(:project, :import_started) - # project.import_state.update_attributes(jid: '123abc') - # - # expect(worker.find_project(project.id).attributes) - # .to eq({ 'id' => nil, 'import_jid' => '123abc' }) - # end - - it 'returns nil for a import state for which the import process failed' do - project = create(:project, :import_failed) - - expect(worker.find_import_state(project.id)).to be_nil - end - - it 'returns nil for a non-existing find_import_state' do - expect(worker.find_import_state(-1)).to be_nil - end - end end diff --git a/spec/workers/gitlab/import/refresh_import_jid_worker_spec.rb b/spec/workers/gitlab/import/refresh_import_jid_worker_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..be4a585d60ed665e86bd0cf424277f85eac2ca15 --- /dev/null +++ b/spec/workers/gitlab/import/refresh_import_jid_worker_spec.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Import::RefreshImportJidWorker, feature_category: :importers do + let(:worker) { described_class.new } + + describe '.perform_in_the_future' do + it 'schedules a job in the future' do + expect(described_class) + .to receive(:perform_in) + .with(5.minutes.to_i, 10, '123') + + described_class.perform_in_the_future(10, '123') + end + end + + describe '#perform' do + let_it_be(:project) { create(:project) } + let(:import_state) { create(:import_state, project: project, jid: '123abc', status: :started) } + + context 'when the project does not exist' do + let(:job_args) { [-1, '123'] } + + it_behaves_like 'an idempotent worker' + + it 'does nothing' do + expect(Gitlab::SidekiqStatus) + .not_to receive(:expire) + + worker.perform(*job_args) + end + end + + context 'when the job is running' do + let(:job_args) { [project.id, '123'] } + + before do + allow(Gitlab::SidekiqStatus) + .to receive(:running?) + .with('123') + .and_return(true) + end + + it_behaves_like 'an idempotent worker' + + it 'refreshes the import JID and reschedules itself' do + expect(Gitlab::SidekiqStatus) + .to receive(:expire) + .with('123', Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION) + + expect(Gitlab::SidekiqStatus) + .to receive(:set) + .with(import_state.jid, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION) + + expect(worker.class) + .to receive(:perform_in_the_future) + .with(project.id, '123') + + worker.perform(*job_args) + end + end + + context 'when the job is no longer running' do + let(:job_args) { [project.id, '123'] } + + before do + allow(Gitlab::SidekiqStatus) + .to receive(:running?) + .with('123') + .and_return(false) + end + + it_behaves_like 'an idempotent worker' + + it 'returns' do + expect(Gitlab::SidekiqStatus) + .not_to receive(:expire) + + expect(Gitlab::SidekiqStatus) + .not_to receive(:set) + + worker.perform(*job_args) + end + end + end +end