-
Notifications
You must be signed in to change notification settings - Fork 371
Replacing validate uniqueness with db constraint on RevisionSidecar model #4950
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
2fa162e
bce39ea
0125953
b04a7fc
9794648
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| Sequel.migration do | ||
| up do | ||
| # remove duplicate entries if they exist | ||
| transaction do | ||
| duplicates = self[:revision_sidecars]. | ||
| select(:revision_guid, :name). | ||
| group(:revision_guid, :name). | ||
| having { count(1) > 1 } | ||
|
|
||
| duplicates.each do |dup| | ||
| ids_to_remove = self[:revision_sidecars]. | ||
| where(revision_guid: dup[:revision_guid], name: dup[:name]). | ||
| select(:id). | ||
| order(:id). | ||
| offset(1). | ||
| map(:id) | ||
| self[:revision_sidecars].where(id: ids_to_remove).delete | ||
| end | ||
|
|
||
| alter_table(:revision_sidecars) do | ||
| unless @db.indexes(:revision_sidecars).key?(:revision_sidecars_revision_guid_name_index) | ||
| add_unique_constraint(%i[revision_guid name], | ||
| name: :revision_sidecars_revision_guid_name_index) | ||
| end | ||
| end | ||
| end | ||
| end | ||
|
|
||
| down do | ||
| alter_table(:revision_sidecars) do | ||
| drop_constraint(:revision_sidecars_revision_guid_name_index, type: :unique) if @db.indexes(:revision_sidecars).key?(:revision_sidecars_revision_guid_name_index) | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| require 'spec_helper' | ||
| require 'migrations/helpers/migration_shared_context' | ||
| RSpec.describe 'add unique constraint to revision sidecar types', isolation: :truncation, type: :migration do | ||
| include_context 'migration' do | ||
| let(:migration_filename) { '20260320141005_add_unique_constraint_to_revision_sidecars.rb' } | ||
| end | ||
|
|
||
| let!(:app) { VCAP::CloudController::AppModel.make } | ||
| let!(:revision) { VCAP::CloudController::RevisionModel.make(:app) } | ||
|
|
||
| it 'remove dublicates, add constraint and revert migration' do | ||
| # ========================================================================================= | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we don't use this kind of comments in other places (or we should not use them) as it makes reading harder from my point of view. A single line comment is fine.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i have followed the previous similar migration and this comment style has been used. |
||
| # SETUP: Create duplicate entries to test the de-duplication logic. | ||
| # ========================================================================================= | ||
| db[:revision_sidecars].insert(guid: SecureRandom.uuid, name: 'app', command: 'command', revision_guid: revision.guid) | ||
| db[:revision_sidecars].insert(guid: SecureRandom.uuid, name: 'app', command: 'command', revision_guid: revision.guid) | ||
| expect(db[:revision_sidecars].where(name: 'app', revision_guid: revision.guid).count).to eq(2) | ||
|
|
||
| # ========================================================================================= | ||
| # UP MIGRATION: Run the migration to apply the unique constraints. | ||
| # ======================================================================================== | ||
| Sequel::Migrator.run(db, migrations_path, target: current_migration_index, allow_missing_migration_files: true) | ||
|
|
||
| # ========================================================================================= | ||
| # ASSERT UP MIGRATION: Verify that duplicates are removed and constraints are enforced. | ||
| # ========================================================================================= | ||
| expect(db[:revision_sidecars].where(name: 'app', revision_guid: revision.guid).count).to eq(1) | ||
| expect(db.indexes(:revision_sidecars)).to include(:revision_sidecars_revision_guid_name_index) | ||
| expect { db[:revision_sidecars].insert(guid: SecureRandom.uuid, name: 'app', command: 'command', revision_guid: revision.guid) }.to raise_error(Sequel::UniqueConstraintViolation) | ||
|
|
||
| # ========================================================================================= | ||
| # TEST IDEMPOTENCY: Running the migration again should not cause any errors. | ||
| # ========================================================================================= | ||
| expect { Sequel::Migrator.run(db, migrations_path, target: current_migration_index, allow_missing_migration_files: true) }.not_to raise_error | ||
|
|
||
| # ========================================================================================= | ||
| # DOWN MIGRATION: Roll back the migration to remove the constraints. | ||
| # ========================================================================================= | ||
| Sequel::Migrator.run(db, migrations_path, target: current_migration_index - 1, allow_missing_migration_files: true) | ||
|
|
||
| # ========================================================================================= | ||
| # ASSERT DOWN MIGRATION: Verify that constraints are removed and duplicates can be re-inserted. | ||
| # ========================================================================================= | ||
| expect(db.indexes(:revision_sidecars)).not_to include(:revision_sidecars_revision_guid_name_index) | ||
| expect { db[:revision_sidecars].insert(guid: SecureRandom.uuid, name: 'app', command: 'command', revision_guid: revision.guid) }.not_to raise_error | ||
| end | ||
| end | ||
Uh oh!
There was an error while loading. Please reload this page.