diff --git a/db/migrations/20180517_create_latest_pact_publication_ids.rb b/db/migrations/20180517_create_latest_pact_publication_ids.rb index 634cc1e9c..88f60b9bf 100644 --- a/db/migrations/20180517_create_latest_pact_publication_ids.rb +++ b/db/migrations/20180517_create_latest_pact_publication_ids.rb @@ -10,7 +10,7 @@ create_table(:latest_pact_publication_ids_by_consumer_versions, charset: 'utf8') do foreign_key :consumer_version_id, :versions, nil: false, on_delete: :cascade foreign_key :provider_id, :pacticipants, nil: false, on_delete: :cascade - foreign_key :pact_publication_id, :pact_publications, nil: false, on_delete: :cascade + foreign_key :pact_publication_id, :pact_publications, nil: false, on_delete: :cascade, unique: true index [:provider_id, :consumer_version_id], unique: true, name: "unq_latest_ppid_prov_conver" end end diff --git a/db/migrations/20180521_create_latest_verification_ids.rb b/db/migrations/20180521_create_latest_verification_ids.rb new file mode 100644 index 000000000..f036ecfaa --- /dev/null +++ b/db/migrations/20180521_create_latest_verification_ids.rb @@ -0,0 +1,18 @@ +Sequel.migration do + up do + # Latest verification_id for each pact version/provider version. + # Keeping track of this in a table rather than having to calculate the + # latest revision speeds queries up. + create_table(:latest_verification_id_for_pact_version_and_provider_version, charset: 'utf8') do + foreign_key :pact_version_id, :pact_versions, nil: false, on_delete: :cascade + foreign_key :provider_version_id, :versions, nil: false, on_delete: :cascade + foreign_key :provider_id, :pacticipants, nil: false, on_delete: :cascade + foreign_key :verification_id, :verifications, nil: false, on_delete: :cascade, unique: true + index [:pact_version_id, :provider_version_id], unique: true, name: "unq_latest_verifid_pvid_provid" + end + end + + down do + drop_table(:latest_verification_id_for_pact_version_and_provider_version) + end +end diff --git a/db/migrations/20180522_migrate_latest_verification_ids.rb b/db/migrations/20180522_migrate_latest_verification_ids.rb new file mode 100644 index 000000000..86bef55e3 --- /dev/null +++ b/db/migrations/20180522_migrate_latest_verification_ids.rb @@ -0,0 +1,18 @@ +Sequel.migration do + up do + # Not sure if we need the provider_id, but it might come in handy + rows = from(:verifications).select_group( + Sequel[:verifications][:pact_version_id], + Sequel[:verifications][:provider_version_id], + Sequel[:versions][:pacticipant_id].as(:provider_id)) + .select_append{ max(verifications[id]).as(verification_id) } + .join(:versions, { Sequel[:verifications][:provider_version_id] => Sequel[:versions][:id] }) + + # The danger with this migration is that a verification created by an old node will be lost + from(:latest_verification_id_for_pact_version_and_provider_version).insert(rows) + end + + down do + + end +end diff --git a/db/migrations/20180523_recreate_views.rb b/db/migrations/20180523_recreate_views.rb new file mode 100644 index 000000000..f46794bdb --- /dev/null +++ b/db/migrations/20180523_recreate_views.rb @@ -0,0 +1,30 @@ +Sequel.migration do + up do + # joining with latest_pact_publication_revision_numbers gets rid of the overwritten + # pact revisions, and the max(verification_id) gets rid of the overwritten + # verifications + create_or_replace_view(:latest_verification_id_for_consumer_version_and_provider_version, + "select pp.consumer_version_id, lv.provider_version_id, lv.verification_id as latest_verification_id + from latest_pact_publication_ids_by_consumer_versions lpp + inner join pact_publications pp + on pp.id = lpp.pact_publication_id + left outer join latest_verification_id_for_pact_version_and_provider_version lv + on lv.pact_version_id = pp.pact_version_id" + ) + + end + + down do + create_or_replace_view(:latest_verification_id_for_consumer_version_and_provider_version, + "select consumer_version_id, provider_version_id, max(verification_id) as latest_verification_id + from matrix + inner join latest_pact_publication_revision_numbers lr + on matrix.consumer_id = lr.consumer_id + and matrix.provider_id = lr.provider_id + and matrix.consumer_version_order = lr.consumer_version_order + and matrix.pact_revision_number = lr.latest_revision_number + group by consumer_version_id, provider_version_id" + ) + + end +end diff --git a/lib/pact_broker/api/resources/verification.rb b/lib/pact_broker/api/resources/verification.rb index 2feecdf7a..736f59763 100644 --- a/lib/pact_broker/api/resources/verification.rb +++ b/lib/pact_broker/api/resources/verification.rb @@ -14,6 +14,8 @@ def content_types_provided [["application/hal+json", :to_json], ["application/json", :to_json]] end + # Remember to update latest_verification_id_for_pact_version_and_provider_version + # if/when DELETE is implemented def allowed_methods ["GET"] end diff --git a/lib/pact_broker/verifications/repository.rb b/lib/pact_broker/verifications/repository.rb index b82d4c4f1..727e46759 100644 --- a/lib/pact_broker/verifications/repository.rb +++ b/lib/pact_broker/verifications/repository.rb @@ -25,6 +25,19 @@ def create verification, provider_version_number, pact verification.pact_version_id = pact_version_id_for(pact) verification.provider_version = version verification.save + update_latest_verification_id(verification) + verification + end + + def update_latest_verification_id verification + if PactBroker::Domain::Verification.db.table_exists?(:latest_verification_id_for_pact_version_and_provider_version) + table = PactBroker::Domain::Verification.db[:latest_verification_id_for_pact_version_and_provider_version] + if table.where(pact_version_id: verification.pact_version_id, provider_version_id: verification.provider_version_id).count == 0 + table.insert(pact_version_id: verification.pact_version_id, provider_version_id: verification.provider_version_id, provider_id: verification.provider_version.pacticipant_id, verification_id: verification.id) + else + table.where(pact_version_id: verification.pact_version_id, provider_version_id: verification.provider_version_id).update(verification_id: verification.id) + end + end end def find consumer_name, provider_name, pact_version_sha, verification_number