Commit f81ebc6a authored by Krasimir Angelov's avatar Krasimir Angelov

Update prepare_async_index migration helper to avoid subtransaction

`safe_find_or_create_by!` creates a savepoint if already in transaction,
which is usually the case for migrations. This updates the helper to
use 'find_or_create_by!` instead in order to avoid subtransactions.

Also changes the helper to update index definition if the record already
exists and there is new definition, something we state in the method
comment but were not actually doing.

https://gitlab.com/gitlab-org/gitlab/-/issues/339667
parent 1d5e32e8
......@@ -55,11 +55,14 @@ module Gitlab
schema_creation = ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaCreation.new(ApplicationRecord.connection)
definition = schema_creation.accept(create_index)
async_index = PostgresAsyncIndex.safe_find_or_create_by!(name: index_name) do |rec|
async_index = PostgresAsyncIndex.find_or_create_by!(name: index_name) do |rec|
rec.table_name = table_name
rec.definition = definition
end
async_index.definition = definition
async_index.save! # No-op if definition is not changed
Gitlab::AppLogger.info(
message: 'Prepared index for async creation',
table_name: async_index.table_name,
......
......@@ -150,6 +150,23 @@ RSpec.describe Gitlab::Database::AsyncIndexes::MigrationHelpers do
migration.prepare_async_index(table_name, 'id')
end.not_to change { index_model.where(name: index_name).count }
end
it 'updates definition if changed' do
index = create(:postgres_async_index, table_name: table_name, name: index_name, definition: '...')
expect do
migration.prepare_async_index(table_name, 'id', name: index_name)
end.to change { index.reload.definition }
end
it 'does not update definition if not changed' do
definition = "CREATE INDEX CONCURRENTLY \"index_#{table_name}_on_id\" ON \"#{table_name}\" (\"id\")"
index = create(:postgres_async_index, table_name: table_name, name: index_name, definition: definition)
expect do
migration.prepare_async_index(table_name, 'id', name: index_name)
end.not_to change { index.reload.updated_at }
end
end
context 'when the async index table does not exist' do
......
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