Skip to content

Commit 97e3dee

Browse files
committed
feat: concurrent migration for postgres db
1 parent 8235de7 commit 97e3dee

2 files changed

Lines changed: 37 additions & 8 deletions

File tree

db/migrations/20260318083940_add_unique_constraint_to_buildpacks.rb

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Sequel.migration do
2+
no_transaction # required for concurrently option on postgres
23
up do
34
transaction do
45
# Remove duplicate entries if they exist
@@ -17,9 +18,23 @@
1718

1819
self[:buildpacks].where(id: ids_to_remove).delete
1920
end
21+
end
2022

23+
if database_type == :postgres
24+
VCAP::Migration.with_concurrent_timeout(self) do
25+
drop_index :buildpacks, nil,
26+
name: :unique_name_and_stack,
27+
concurrently: true,
28+
if_exists: true
29+
add_index :buildpacks, %i[name stack lifecycle],
30+
name: :buildpacks_name_stack_lifecycle_index,
31+
unique: true,
32+
concurrently: true,
33+
if_not_exists: true
34+
end
35+
else
2136
alter_table(:buildpacks) do
22-
# rubocop:disable Sequel/ConcurrentIndex
37+
# rubocop:disable Sequel/ConcurrentIndex -- MySQL does not support concurrent index operations
2338
drop_index %i[name stack], name: :unique_name_and_stack if @db.indexes(:buildpacks).key?(:unique_name_and_stack)
2439
unless @db.indexes(:buildpacks).key?(:buildpacks_name_stack_lifecycle_index)
2540
add_index %i[name stack lifecycle], unique: true,
@@ -31,11 +46,25 @@
3146
end
3247

3348
down do
34-
alter_table(:buildpacks) do
35-
# rubocop:disable Sequel/ConcurrentIndex
36-
drop_index %i[name stack lifecycle], name: :buildpacks_name_stack_lifecycle_index if @db.indexes(:buildpacks).key?(:buildpacks_name_stack_lifecycle_index)
37-
add_index %i[name stack], unique: true, name: :unique_name_and_stack unless @db.indexes(:buildpacks).key?(:unique_name_and_stack)
38-
# rubocop:enable Sequel/ConcurrentIndex
49+
if database_type == :postgres
50+
VCAP::Migration.with_concurrent_timeout(self) do
51+
drop_index :buildpacks, nil,
52+
name: :buildpacks_name_stack_lifecycle_index,
53+
concurrently: true,
54+
if_exists: true
55+
add_index :buildpacks, %i[name stack],
56+
name: :unique_name_and_stack,
57+
unique: true,
58+
concurrently: true,
59+
if_not_exists: true
60+
end
61+
else
62+
alter_table(:buildpacks) do
63+
# rubocop:disable Sequel/ConcurrentIndex -- MySQL does not support concurrent index operations
64+
drop_index %i[name stack lifecycle], name: :buildpacks_name_stack_lifecycle_index if @db.indexes(:buildpacks).key?(:buildpacks_name_stack_lifecycle_index)
65+
add_index %i[name stack], unique: true, name: :unique_name_and_stack unless @db.indexes(:buildpacks).key?(:unique_name_and_stack)
66+
# rubocop:enable Sequel/ConcurrentIndex
67+
end
3968
end
4069
end
4170
end

spec/unit/models/runtime/buildpack_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def ordered_buildpacks
8181
context 'when unique constraint violation is occures' do
8282
let(:stack) { Stack.make }
8383

84-
it 'raise validation error when name, stack and lifecyle is same' do
84+
it 'raises validation error when name, stack and lifecyle is same' do
8585
Buildpack.create(name: 'oscar', stack: stack.name, lifecycle: 'cnb')
8686
expect do
8787
Buildpack.create(name: 'oscar', stack: stack.name, lifecycle: 'cnb')
@@ -90,7 +90,7 @@ def ordered_buildpacks
9090
end
9191
end
9292

93-
it 'raise validation error different than the unique name, stack and lifecyle' do
93+
it 'raises validation error different than the unique name, stack and lifecyle' do
9494
existing = Buildpack.create(name: 'oscar', stack: stack.name, lifecycle: 'cnb')
9595
duplicate_guid = Buildpack.new(name: 'other', stack: stack.name, lifecycle: 'cnb')
9696
duplicate_guid.guid = existing.guid

0 commit comments

Comments
 (0)