diff --git a/db/docs/batched_background_migrations/backfill_packages_pypi_metadata_project_id.yml b/db/docs/batched_background_migrations/backfill_packages_pypi_metadata_project_id.yml new file mode 100644 index 0000000000000000000000000000000000000000..c6d1e82e25443acf113b248ab7f96003f13e7cd0 --- /dev/null +++ b/db/docs/batched_background_migrations/backfill_packages_pypi_metadata_project_id.yml @@ -0,0 +1,9 @@ +--- +migration_job_name: BackfillPackagesPypiMetadataProjectId +description: Backfills sharding key `packages_pypi_metadata.project_id` from `packages_packages`. +feature_category: package_registry +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/167608 +milestone: '17.5' +queued_migration_version: 20240930121830 +finalize_after: '2024-10-22' +finalized_by: # version of the migration that finalized this BBM diff --git a/db/docs/packages_pypi_metadata.yml b/db/docs/packages_pypi_metadata.yml index 95b1f0f635fba3f4ce98212656af02f9aba2f50c..1304012e0b3fca7c37a74e4a0a8ad3e6c9bb35b6 100644 --- a/db/docs/packages_pypi_metadata.yml +++ b/db/docs/packages_pypi_metadata.yml @@ -19,3 +19,4 @@ desired_sharding_key: table: packages_packages sharding_key: project_id belongs_to: package +desired_sharding_key_migration_job_name: BackfillPackagesPypiMetadataProjectId diff --git a/db/migrate/20240930121826_add_project_id_to_packages_pypi_metadata.rb b/db/migrate/20240930121826_add_project_id_to_packages_pypi_metadata.rb new file mode 100644 index 0000000000000000000000000000000000000000..2c908f3599e9360c924501b45fb4c6f3690a6413 --- /dev/null +++ b/db/migrate/20240930121826_add_project_id_to_packages_pypi_metadata.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddProjectIdToPackagesPypiMetadata < Gitlab::Database::Migration[2.2] + milestone '17.5' + + def change + add_column :packages_pypi_metadata, :project_id, :bigint + end +end diff --git a/db/post_migrate/20240930121827_index_packages_pypi_metadata_on_project_id.rb b/db/post_migrate/20240930121827_index_packages_pypi_metadata_on_project_id.rb new file mode 100644 index 0000000000000000000000000000000000000000..d4427fa3d06f8586d3c211f06767103195d8c4c3 --- /dev/null +++ b/db/post_migrate/20240930121827_index_packages_pypi_metadata_on_project_id.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class IndexPackagesPypiMetadataOnProjectId < Gitlab::Database::Migration[2.2] + milestone '17.5' + disable_ddl_transaction! + + INDEX_NAME = 'index_packages_pypi_metadata_on_project_id' + + def up + add_concurrent_index :packages_pypi_metadata, :project_id, name: INDEX_NAME + end + + def down + remove_concurrent_index_by_name :packages_pypi_metadata, INDEX_NAME + end +end diff --git a/db/post_migrate/20240930121828_add_packages_pypi_metadata_project_id_fk.rb b/db/post_migrate/20240930121828_add_packages_pypi_metadata_project_id_fk.rb new file mode 100644 index 0000000000000000000000000000000000000000..f4114ab8d4d0d3e139f7d11e5e1730d396a94950 --- /dev/null +++ b/db/post_migrate/20240930121828_add_packages_pypi_metadata_project_id_fk.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class AddPackagesPypiMetadataProjectIdFk < Gitlab::Database::Migration[2.2] + milestone '17.5' + disable_ddl_transaction! + + def up + add_concurrent_foreign_key :packages_pypi_metadata, :projects, column: :project_id, on_delete: :cascade + end + + def down + with_lock_retries do + remove_foreign_key :packages_pypi_metadata, column: :project_id + end + end +end diff --git a/db/post_migrate/20240930121829_add_packages_pypi_metadata_project_id_trigger.rb b/db/post_migrate/20240930121829_add_packages_pypi_metadata_project_id_trigger.rb new file mode 100644 index 0000000000000000000000000000000000000000..c9eeca1f951b081b6b160c18607f80bae3aa0530 --- /dev/null +++ b/db/post_migrate/20240930121829_add_packages_pypi_metadata_project_id_trigger.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class AddPackagesPypiMetadataProjectIdTrigger < Gitlab::Database::Migration[2.2] + milestone '17.5' + + def up + install_sharding_key_assignment_trigger( + table: :packages_pypi_metadata, + sharding_key: :project_id, + parent_table: :packages_packages, + parent_sharding_key: :project_id, + foreign_key: :package_id + ) + end + + def down + remove_sharding_key_assignment_trigger( + table: :packages_pypi_metadata, + sharding_key: :project_id, + parent_table: :packages_packages, + parent_sharding_key: :project_id, + foreign_key: :package_id + ) + end +end diff --git a/db/post_migrate/20240930121830_queue_backfill_packages_pypi_metadata_project_id.rb b/db/post_migrate/20240930121830_queue_backfill_packages_pypi_metadata_project_id.rb new file mode 100644 index 0000000000000000000000000000000000000000..2a4a613166bba58af6d6d25b459a6ca4536b064c --- /dev/null +++ b/db/post_migrate/20240930121830_queue_backfill_packages_pypi_metadata_project_id.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +class QueueBackfillPackagesPypiMetadataProjectId < Gitlab::Database::Migration[2.2] + milestone '17.5' + restrict_gitlab_migration gitlab_schema: :gitlab_main_cell + + MIGRATION = "BackfillPackagesPypiMetadataProjectId" + DELAY_INTERVAL = 2.minutes + BATCH_SIZE = 1000 + SUB_BATCH_SIZE = 100 + + def up + queue_batched_background_migration( + MIGRATION, + :packages_pypi_metadata, + :package_id, + :project_id, + :packages_packages, + :project_id, + :package_id, + job_interval: DELAY_INTERVAL, + batch_size: BATCH_SIZE, + sub_batch_size: SUB_BATCH_SIZE + ) + end + + def down + delete_batched_background_migration( + MIGRATION, + :packages_pypi_metadata, + :package_id, + [ + :project_id, + :packages_packages, + :project_id, + :package_id + ] + ) + end +end diff --git a/db/schema_migrations/20240930121826 b/db/schema_migrations/20240930121826 new file mode 100644 index 0000000000000000000000000000000000000000..cee1343df809d392d2e04051ab76e84b8c2da8c3 --- /dev/null +++ b/db/schema_migrations/20240930121826 @@ -0,0 +1 @@ +8bcd22d80c42565f63b10f6e770d1fc6e298155e23b9d600322f0a60162d8f6f \ No newline at end of file diff --git a/db/schema_migrations/20240930121827 b/db/schema_migrations/20240930121827 new file mode 100644 index 0000000000000000000000000000000000000000..ba8062bd856d9e5a0fdb85cb1f9fb2ce6870c521 --- /dev/null +++ b/db/schema_migrations/20240930121827 @@ -0,0 +1 @@ +a218cdf1cd33cf8aa2be34db650ce3acee4ee8908924e02fe3eeb10834d0f902 \ No newline at end of file diff --git a/db/schema_migrations/20240930121828 b/db/schema_migrations/20240930121828 new file mode 100644 index 0000000000000000000000000000000000000000..cc66a479c0b23b2a26f03e134187a3b8253a9a9b --- /dev/null +++ b/db/schema_migrations/20240930121828 @@ -0,0 +1 @@ +9e855dcd7310302142e9c434f27a57df6ec1fc6abe7a615833e4427e13975871 \ No newline at end of file diff --git a/db/schema_migrations/20240930121829 b/db/schema_migrations/20240930121829 new file mode 100644 index 0000000000000000000000000000000000000000..a1897ba541ce93c6682228fd28980e3fbe3e879c --- /dev/null +++ b/db/schema_migrations/20240930121829 @@ -0,0 +1 @@ +fb139a0a83d84d8a4c296974ac6fc5698810425b5d0c112878fc47ffd2bf3237 \ No newline at end of file diff --git a/db/schema_migrations/20240930121830 b/db/schema_migrations/20240930121830 new file mode 100644 index 0000000000000000000000000000000000000000..458584909bb21e44c097a55f2753fefa923241f4 --- /dev/null +++ b/db/schema_migrations/20240930121830 @@ -0,0 +1 @@ +c17f2fa09d28e36f0d8f5ca0fba72e303090a27fb505416199fb531b8cdcdbb0 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 65102b234b3f014dea899e8d44307c20c78f236e..28f58af15e0cee5145004dfb9fdfd4642c8bc930 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1337,6 +1337,22 @@ RETURN NEW; END $$; +CREATE FUNCTION trigger_44ff19ad0ab2() RETURNS trigger + LANGUAGE plpgsql + AS $$ +BEGIN +IF NEW."project_id" IS NULL THEN + SELECT "project_id" + INTO NEW."project_id" + FROM "packages_packages" + WHERE "packages_packages"."id" = NEW."package_id"; +END IF; + +RETURN NEW; + +END +$$; + CREATE FUNCTION trigger_46ebe375f632() RETURNS trigger LANGUAGE plpgsql AS $$ @@ -15636,6 +15652,7 @@ CREATE TABLE packages_pypi_metadata ( author_email text, description text, description_content_type text, + project_id bigint, CONSTRAINT check_0d9aed55b2 CHECK ((required_python IS NOT NULL)), CONSTRAINT check_222e4f5b58 CHECK ((char_length(keywords) <= 1024)), CONSTRAINT check_2d3ed32225 CHECK ((char_length(metadata_version) <= 16)), @@ -30162,6 +30179,8 @@ CREATE INDEX index_packages_packages_on_project_id_and_version ON packages_packa CREATE INDEX index_packages_project_id_name_partial_for_nuget ON packages_packages USING btree (project_id, name) WHERE (((name)::text <> 'NuGet.Temporary.Package'::text) AND (version IS NOT NULL) AND (package_type = 4)); +CREATE INDEX index_packages_pypi_metadata_on_project_id ON packages_pypi_metadata USING btree (project_id); + CREATE INDEX index_packages_rpm_metadata_on_package_id ON packages_rpm_metadata USING btree (package_id); CREATE INDEX index_packages_rpm_metadata_on_project_id ON packages_rpm_metadata USING btree (project_id); @@ -33612,6 +33631,8 @@ CREATE TRIGGER trigger_43484cb41aca BEFORE INSERT OR UPDATE ON wiki_repository_s CREATE TRIGGER trigger_44558add1625 BEFORE INSERT OR UPDATE ON merge_request_assignees FOR EACH ROW EXECUTE FUNCTION trigger_44558add1625(); +CREATE TRIGGER trigger_44ff19ad0ab2 BEFORE INSERT OR UPDATE ON packages_pypi_metadata FOR EACH ROW EXECUTE FUNCTION trigger_44ff19ad0ab2(); + CREATE TRIGGER trigger_46ebe375f632 BEFORE INSERT OR UPDATE ON epic_issues FOR EACH ROW EXECUTE FUNCTION trigger_46ebe375f632(); CREATE TRIGGER trigger_49862b4b3035 BEFORE INSERT OR UPDATE ON approval_group_rules_protected_branches FOR EACH ROW EXECUTE FUNCTION trigger_49862b4b3035(); @@ -34611,6 +34632,9 @@ ALTER TABLE ONLY packages_package_files ALTER TABLE p_ci_builds ADD CONSTRAINT fk_87f4cefcda_p FOREIGN KEY (upstream_pipeline_partition_id, upstream_pipeline_id) REFERENCES p_ci_pipelines(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; +ALTER TABLE ONLY packages_pypi_metadata + ADD CONSTRAINT fk_884056a10f FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; + ALTER TABLE ONLY approval_group_rules_users ADD CONSTRAINT fk_888a0df3b7 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; diff --git a/lib/gitlab/background_migration/backfill_packages_pypi_metadata_project_id.rb b/lib/gitlab/background_migration/backfill_packages_pypi_metadata_project_id.rb new file mode 100644 index 0000000000000000000000000000000000000000..501c88d305a6b175861995ab7fd8eb19ce26045f --- /dev/null +++ b/lib/gitlab/background_migration/backfill_packages_pypi_metadata_project_id.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + class BackfillPackagesPypiMetadataProjectId < BackfillDesiredShardingKeyJob + operation_name :backfill_packages_pypi_metadata_project_id + feature_category :package_registry + end + end +end diff --git a/spec/lib/gitlab/background_migration/backfill_packages_pypi_metadata_project_id_spec.rb b/spec/lib/gitlab/background_migration/backfill_packages_pypi_metadata_project_id_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..8de8dfd476e87096e459776d5485bcb41e087c44 --- /dev/null +++ b/spec/lib/gitlab/background_migration/backfill_packages_pypi_metadata_project_id_spec.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::BackfillPackagesPypiMetadataProjectId, + feature_category: :package_registry, + schema: 20240930121826 do + include_examples 'desired sharding key backfill job' do + let(:batch_table) { :packages_pypi_metadata } + let(:batch_column) { :package_id } + let(:backfill_column) { :project_id } + let(:backfill_via_table) { :packages_packages } + let(:backfill_via_column) { :project_id } + let(:backfill_via_foreign_key) { :package_id } + end +end diff --git a/spec/migrations/20240930121830_queue_backfill_packages_pypi_metadata_project_id_spec.rb b/spec/migrations/20240930121830_queue_backfill_packages_pypi_metadata_project_id_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..dbe38483f8c035bad4781df83ad51132c627ad7b --- /dev/null +++ b/spec/migrations/20240930121830_queue_backfill_packages_pypi_metadata_project_id_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe QueueBackfillPackagesPypiMetadataProjectId, feature_category: :package_registry do + let!(:batched_migration) { described_class::MIGRATION } + + it 'schedules a new batched migration' do + reversible_migration do |migration| + migration.before -> { + expect(batched_migration).not_to have_scheduled_batched_migration + } + + migration.after -> { + expect(batched_migration).to have_scheduled_batched_migration( + table_name: :packages_pypi_metadata, + column_name: :package_id, + interval: described_class::DELAY_INTERVAL, + batch_size: described_class::BATCH_SIZE, + sub_batch_size: described_class::SUB_BATCH_SIZE, + gitlab_schema: :gitlab_main_cell, + job_arguments: [ + :project_id, + :packages_packages, + :project_id, + :package_id + ] + ) + } + end + end +end