Commit 4f4269ad authored by Valery Sizov's avatar Valery Sizov Committed by Michael Kozono

Add unique foreign keys to Geo registries

We need to prevent duplicates for the registries
parent c4af11fa
---
title: 'Geo: Add unique constraints to container repository and terraform state registries'
merge_request: 54841
author:
type: fixed
# frozen_string_literal: true
class AddUniqueIndexOnContainerRepositoryRegistry < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
OLD_INDEX_NAME = 'index_container_repository_registry_on_repository_id'
NEW_INDEX_NAME = 'index_container_repository_registry_repository_id_unique'
disable_ddl_transaction!
def up
# Removing duplicated records that would prevent creating an unique index.
execute <<-SQL
DELETE FROM container_repository_registry
USING (
SELECT container_repository_id, MIN(id) as min_id
FROM container_repository_registry
GROUP BY container_repository_id
HAVING COUNT(id) > 1
) as container_repository_registry_duplicates
WHERE container_repository_registry_duplicates.container_repository_id = container_repository_registry.container_repository_id
AND container_repository_registry_duplicates.min_id <> container_repository_registry.id
SQL
add_concurrent_index(:container_repository_registry,
:container_repository_id,
unique: true,
name: NEW_INDEX_NAME)
remove_concurrent_index_by_name :container_repository_registry, OLD_INDEX_NAME
end
def down
add_concurrent_index(:container_repository_registry,
:container_repository_id,
name: OLD_INDEX_NAME)
remove_concurrent_index_by_name :container_repository_registry, NEW_INDEX_NAME
end
end
# frozen_string_literal: true
class AddUniqueIndexOnTerraformStateVersionRegistry < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
OLD_INDEX_NAME = 'index_tf_state_versions_registry_on_tf_state_versions_id'
NEW_INDEX_NAME = 'index_tf_state_versions_registry_tf_state_versions_id_unique'
disable_ddl_transaction!
def up
# Removing duplicated records that would prevent creating an unique index.
execute <<-SQL
DELETE FROM terraform_state_version_registry
USING (
SELECT terraform_state_version_id, MIN(id) as min_id
FROM terraform_state_version_registry
GROUP BY terraform_state_version_id
HAVING COUNT(id) > 1
) as terraform_state_version_registry_duplicates
WHERE terraform_state_version_registry_duplicates.terraform_state_version_id = terraform_state_version_registry.terraform_state_version_id
AND terraform_state_version_registry_duplicates.min_id <> terraform_state_version_registry.id
SQL
add_concurrent_index(:terraform_state_version_registry,
:terraform_state_version_id,
unique: true,
name: NEW_INDEX_NAME)
remove_concurrent_index_by_name :terraform_state_version_registry, OLD_INDEX_NAME
end
def down
add_concurrent_index(:terraform_state_version_registry,
:terraform_state_version_id,
name: OLD_INDEX_NAME)
remove_concurrent_index_by_name :terraform_state_version_registry, NEW_INDEX_NAME
end
end
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2021_02_08_175408) do ActiveRecord::Schema.define(version: 2021_02_17_020156) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -23,7 +23,7 @@ ActiveRecord::Schema.define(version: 2021_02_08_175408) do ...@@ -23,7 +23,7 @@ ActiveRecord::Schema.define(version: 2021_02_08_175408) do
t.datetime "retry_at" t.datetime "retry_at"
t.datetime "last_synced_at" t.datetime "last_synced_at"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.index ["container_repository_id"], name: "index_container_repository_registry_on_repository_id" t.index ["container_repository_id"], name: "index_container_repository_registry_repository_id_unique", unique: true
t.index ["retry_at"], name: "index_container_repository_registry_on_retry_at" t.index ["retry_at"], name: "index_container_repository_registry_on_retry_at"
t.index ["state"], name: "index_container_repository_registry_on_state" t.index ["state"], name: "index_container_repository_registry_on_state"
end end
...@@ -217,7 +217,7 @@ ActiveRecord::Schema.define(version: 2021_02_08_175408) do ...@@ -217,7 +217,7 @@ ActiveRecord::Schema.define(version: 2021_02_08_175408) do
t.text "last_sync_failure" t.text "last_sync_failure"
t.index ["retry_at"], name: "index_terraform_state_version_registry_on_retry_at" t.index ["retry_at"], name: "index_terraform_state_version_registry_on_retry_at"
t.index ["state"], name: "index_terraform_state_version_registry_on_state" t.index ["state"], name: "index_terraform_state_version_registry_on_state"
t.index ["terraform_state_version_id"], name: "index_tf_state_versions_registry_on_tf_state_versions_id" t.index ["terraform_state_version_id"], name: "index_tf_state_versions_registry_tf_state_versions_id_unique", unique: true
end end
end end
...@@ -24,5 +24,9 @@ FactoryBot.define do ...@@ -24,5 +24,9 @@ FactoryBot.define do
last_synced_at { 1.day.ago } last_synced_at { 1.day.ago }
retry_count { 0 } retry_count { 0 }
end end
trait :with_repository_id do
sequence(:container_repository_id)
end
end end
end end
...@@ -6,7 +6,7 @@ RSpec.describe Geo::ContainerRepositoryRegistry, :geo do ...@@ -6,7 +6,7 @@ RSpec.describe Geo::ContainerRepositoryRegistry, :geo do
include ::EE::GeoHelpers include ::EE::GeoHelpers
it_behaves_like 'a BulkInsertSafe model', Geo::ContainerRepositoryRegistry do it_behaves_like 'a BulkInsertSafe model', Geo::ContainerRepositoryRegistry do
let(:valid_items_for_bulk_insertion) { build_list(:container_repository_registry, 10, container_repository: create(:container_repository), created_at: Time.zone.now) } let(:valid_items_for_bulk_insertion) { build_list(:container_repository_registry, 10, :with_repository_id, created_at: Time.zone.now) }
let(:invalid_items_for_bulk_insertion) { [] } # class does not have any validations defined let(:invalid_items_for_bulk_insertion) { [] } # class does not have any validations defined
end end
......
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