diff --git a/app/models/project.rb b/app/models/project.rb index 45d334bd09a0e464c477353b3560422d7fb5bf40..499e5d0fd90ad7a654e367d5a784b6f86be1baf7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -2318,7 +2318,13 @@ def pipeline_status def add_export_job(current_user:, after_export_strategy: nil, params: {}) check_project_export_limit! - job_id = ProjectExportWorker.perform_async(current_user.id, self.id, after_export_strategy, params) + job_id = if Feature.enabled?(:parallel_project_export, current_user) + Projects::ImportExport::CreateRelationExportsWorker + .perform_async(current_user.id, self.id, after_export_strategy, params) + else + ProjectExportWorker + .perform_async(current_user.id, self.id, after_export_strategy, params) + end if job_id Gitlab::AppLogger.info "Export job started for project ID #{self.id} with job ID #{job_id}" diff --git a/app/workers/projects/import_export/create_relation_exports_worker.rb b/app/workers/projects/import_export/create_relation_exports_worker.rb index e115c8917b183544e61ab1a375500876f2204baa..ac5fd343a6ce9d07269bc35d74ae6605a70fe015 100644 --- a/app/workers/projects/import_export/create_relation_exports_worker.rb +++ b/app/workers/projects/import_export/create_relation_exports_worker.rb @@ -33,14 +33,14 @@ def perform(user_id, project_id, after_export_strategy = {}, params = {}) RelationExportWorker.with_status.perform_async(relation_export.id, user_id, params) end + project_export_job.start! + WaitRelationExportsWorker.perform_in( INITIAL_DELAY, project_export_job.id, user_id, after_export_strategy ) - - project_export_job.start! end # rubocop: enable CodeReuse/ActiveRecord end diff --git a/config/feature_flags/development/parallel_project_export.yml b/config/feature_flags/development/parallel_project_export.yml new file mode 100644 index 0000000000000000000000000000000000000000..da4e9a0417e484cf0f8e120e2c27e9cccc728bc5 --- /dev/null +++ b/config/feature_flags/development/parallel_project_export.yml @@ -0,0 +1,8 @@ +--- +name: parallel_project_export +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/145165 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442337 +milestone: '16.10' +type: development +group: group::import and integrate +default_enabled: false diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index bc3a11934b5a075ed5ae433a8fd2cca1fdaba41e..438cf3dd410f3947f08f970e04bc4a051a38a8c4 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -7593,34 +7593,56 @@ def has_external_wiki let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project) } - context 'when project storage_size does not exceed the application setting max_export_size' do - it 'starts project export worker' do - stub_application_setting(max_export_size: 1) - allow(project.statistics).to receive(:storage_size).and_return(0.megabytes) - - expect(ProjectExportWorker).to receive(:perform_async).with(user.id, project.id, nil, {}) + context 'when parallel_project_export feature flag is enabled' do + it 'enqueues CreateionProjectExportWorker' do + expect(Projects::ImportExport::CreateRelationExportsWorker) + .to receive(:perform_async) + .with(user.id, project.id, nil, {}) project.add_export_job(current_user: user) end end - context 'when project storage_size exceeds the application setting max_export_size' do - it 'raises Project::ExportLimitExceeded' do - stub_application_setting(max_export_size: 1) - allow(project.statistics).to receive(:storage_size).and_return(2.megabytes) - - expect(ProjectExportWorker).not_to receive(:perform_async).with(user.id, project.id, nil, {}) - expect { project.add_export_job(current_user: user) }.to raise_error(Project::ExportLimitExceeded) + context 'when parallel_project_export feature flag is disabled' do + before do + stub_feature_flags(parallel_project_export: false) end - end - context 'when application setting max_export_size is not set' do - it 'starts project export worker' do - allow(project.statistics).to receive(:storage_size).and_return(2.megabytes) + it 'enquques ProjectExportWorker' do expect(ProjectExportWorker).to receive(:perform_async).with(user.id, project.id, nil, {}) project.add_export_job(current_user: user) end + + context 'when project storage_size does not exceed the application setting max_export_size' do + it 'starts project export worker' do + stub_application_setting(max_export_size: 1) + allow(project.statistics).to receive(:storage_size).and_return(0.megabytes) + + expect(ProjectExportWorker).to receive(:perform_async).with(user.id, project.id, nil, {}) + + project.add_export_job(current_user: user) + end + end + + context 'when project storage_size exceeds the application setting max_export_size' do + it 'raises Project::ExportLimitExceeded' do + stub_application_setting(max_export_size: 1) + allow(project.statistics).to receive(:storage_size).and_return(2.megabytes) + + expect(ProjectExportWorker).not_to receive(:perform_async).with(user.id, project.id, nil, {}) + expect { project.add_export_job(current_user: user) }.to raise_error(Project::ExportLimitExceeded) + end + end + + context 'when application setting max_export_size is not set' do + it 'starts project export worker' do + allow(project.statistics).to receive(:storage_size).and_return(2.megabytes) + expect(ProjectExportWorker).to receive(:perform_async).with(user.id, project.id, nil, {}) + + project.add_export_job(current_user: user) + end + end end end diff --git a/spec/requests/api/project_export_spec.rb b/spec/requests/api/project_export_spec.rb index 6d5591d75002f30ed4cda78d69c47a6f69c1ccc5..02c2b9bceb211d55d0e37b9c04be725239e4eb5e 100644 --- a/spec/requests/api/project_export_spec.rb +++ b/spec/requests/api/project_export_spec.rb @@ -519,15 +519,27 @@ end context 'when overriding description' do - it 'starts', :sidekiq_might_not_need_inline do - params = { description: "Foo" } + context 'when parallel_project_export feature flag is disabled' do + it 'starts export service', :sidekiq_might_not_need_inline do + stub_feature_flags(parallel_project_export: false) - expect_next_instance_of(Projects::ImportExport::ExportService) do |service| - expect(service).to receive(:execute) + params = { description: "Foo" } + + expect_next_instance_of(Projects::ImportExport::ExportService) do |service| + expect(service).to receive(:execute) + end + post api(path, project.first_owner), params: params + + expect(response).to have_gitlab_http_status(:accepted) end - post api(path, project.first_owner), params: params + end - expect(response).to have_gitlab_http_status(:accepted) + context 'when parallel_project_export feature flag is enabled' do + it 'enqueues CreateRelationExportsWorker' do + expect(Projects::ImportExport::CreateRelationExportsWorker).to receive(:perform_async) + + post api(path, project.first_owner), params: params + end end end end