Skip to content

Commit 9e5ea8b

Browse files
authored
feat(matrix): speed up query for UI by reducing the number of joins and removing unncessary criteria (pact-foundation#332)
* Add a created_at column to the latest pacts/latest verifications tables * Use the created_at columns newly created on latest_pact_publication_ids_for_consumer_versions and latest_verification_id_for_pact_version_and_provider_version to avoid having to join in the versions tables to order the matrix query rows * speed up matrix UI page by not joining verifications table when no version is specified * speed up matrix query by removing unncessary null check for provider versions when we are only querying by pacticipant names
1 parent a4ccf61 commit 9e5ea8b

20 files changed

+221
-126
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Sequel.migration do
2+
change do
3+
# TODO
4+
# alter_table(:latest_pact_publication_ids_for_consumer_versions) do
5+
# set_column_not_null(:created_at)
6+
# end
7+
add_column(:latest_pact_publication_ids_for_consumer_versions, :created_at, DateTime)
8+
end
9+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Sequel.migration do
2+
change do
3+
# TODO
4+
# alter_table(:latest_verification_id_for_pact_version_and_provider_version) do
5+
# set_column_not_null(:created_at)
6+
# end
7+
add_column(:latest_verification_id_for_pact_version_and_provider_version, :created_at, DateTime)
8+
end
9+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
require 'pact_broker/db/data_migrations/helpers'
2+
3+
module PactBroker
4+
module DB
5+
module DataMigrations
6+
class SetCreatedAtForLatestPactPublications
7+
def self.call connection
8+
# pact ordering goes by creation date of the consumer version
9+
connection[:latest_pact_publication_ids_for_consumer_versions]
10+
query = "UPDATE latest_pact_publication_ids_for_consumer_versions
11+
SET created_at = (SELECT created_at
12+
FROM versions
13+
WHERE id = latest_pact_publication_ids_for_consumer_versions.consumer_version_id)
14+
WHERE created_at IS NULL"
15+
connection.run(query)
16+
end
17+
18+
def self.columns_exist?(connection)
19+
column_exists?(connection, :latest_pact_publication_ids_for_consumer_versions, :created_at) &&
20+
column_exists?(connection, :pact_publications, :created_at)
21+
end
22+
end
23+
end
24+
end
25+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
require 'pact_broker/db/data_migrations/helpers'
2+
3+
module PactBroker
4+
module DB
5+
module DataMigrations
6+
class SetCreatedAtForLatestVerifications
7+
def self.call connection
8+
connection[:latest_verification_id_for_pact_version_and_provider_version]
9+
query = "UPDATE latest_verification_id_for_pact_version_and_provider_version
10+
SET created_at = (SELECT created_at
11+
FROM verifications
12+
WHERE id = latest_verification_id_for_pact_version_and_provider_version.verification_id)
13+
WHERE created_at is null"
14+
connection.run(query)
15+
end
16+
17+
def self.columns_exist?(connection)
18+
column_exists?(connection, :latest_verification_id_for_pact_version_and_provider_version, :created_at) &&
19+
column_exists?(connection, :verifications, :created_at)
20+
end
21+
end
22+
end
23+
end
24+
end

lib/pact_broker/db/migrate_data.rb

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ def self.call database_connection, options = {}
1919
DataMigrations::SetLatestVersionSequenceValue.call(database_connection)
2020
DataMigrations::SetWebhooksEnabled.call(database_connection)
2121
DataMigrations::DeleteDeprecatedWebhookExecutions.call(database_connection)
22+
DataMigrations::SetCreatedAtForLatestPactPublications.call(database_connection)
23+
DataMigrations::SetCreatedAtForLatestVerifications.call(database_connection)
2224
end
2325
end
2426
end

lib/pact_broker/matrix/every_row.rb

+11-5
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,22 @@ class EveryRow < PactBroker::Matrix::QuickRow
88
P_V_JOIN = { Sequel[:p][:pact_version_id] => Sequel[:v][:pact_version_id] }
99

1010
PACT_COLUMNS = [
11+
Sequel[:p][:consumer_id],
12+
Sequel[:p][:provider_id],
13+
Sequel[:p][:consumer_version_id],
1114
Sequel[:p][:id].as(:pact_publication_id),
1215
Sequel[:p][:pact_version_id],
13-
Sequel[:p][:revision_number].as(:pact_revision_number)
16+
Sequel[:p][:revision_number].as(:pact_revision_number),
17+
Sequel[:p][:created_at].as(:consumer_version_created_at),
18+
Sequel[:p][:id].as(:pact_order)
1419
]
1520
VERIFICATION_COLUMNS = [
16-
Sequel[:v][:id].as(:verification_id)
21+
Sequel[:v][:id].as(:verification_id),
22+
Sequel[:v][:provider_version_id],
23+
Sequel[:v][:created_at].as(:provider_version_created_at)
1724
]
1825

19-
ALL_COLUMNS = [LAST_ACTION_DATE] + CONSUMER_COLUMNS + CONSUMER_VERSION_COLUMNS + PACT_COLUMNS +
20-
PROVIDER_COLUMNS + PROVIDER_VERSION_COLUMNS + VERIFICATION_COLUMNS
26+
ALL_COLUMNS = PACT_COLUMNS + VERIFICATION_COLUMNS
2127

2228
SELECT_ALL_COLUMN_ARGS = [:select_all_columns] + ALL_COLUMNS
2329
dataset_module do
@@ -29,7 +35,7 @@ def join_verifications
2935

3036
def verifications_for(query_ids)
3137
db[:verifications]
32-
.select(:id, :pact_version_id, :provider_id, :provider_version_id)
38+
.select(:id, :pact_version_id, :provider_id, :provider_version_id, :created_at)
3339
.where {
3440
Sequel.&(
3541
QueryBuilder.consumer_in_pacticipant_ids(query_ids),

lib/pact_broker/matrix/parse_query.rb

+6
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,17 @@ def self.call query
2626
if params.key?('latestby') && params['latestby'] != ''
2727
options[:latestby] = params['latestby']
2828
end
29+
30+
if params.key?('days') && params['days'] != ''
31+
options[:days] = params['days'].to_i
32+
end
33+
2934
if params.key?('limit') && params['limit'] != ''
3035
options[:limit] = params['limit']
3136
else
3237
options[:limit] = "100"
3338
end
39+
3440
if params.key?('latest') && params['latest'] != ''
3541
options[:latest] = params['latest'] == 'true'
3642
end

lib/pact_broker/matrix/query_builder.rb

+23-11
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,36 @@
11
module PactBroker
22
module Matrix
33
class QueryBuilder
4-
def self.provider_or_provider_version_matches(query_ids, verifications_qualifier = nil)
5-
Sequel.|(*provider_or_provider_version_criteria(query_ids, verifications_qualifier))
4+
def self.provider_or_provider_version_matches(query_ids, provider_version_qualifier = nil, provider_qualifier = nil)
5+
Sequel.|(*provider_or_provider_version_criteria(query_ids, provider_version_qualifier, provider_qualifier))
66
end
77

8-
def self.provider_or_provider_version_matches_or_pact_unverified(query_ids, verifications_qualifier = nil)
9-
ors = provider_or_provider_version_criteria(query_ids, verifications_qualifier)
10-
11-
ors << {
12-
qualify(:p, :provider_id) => query_ids.all_pacticipant_ids,
13-
qualify(verifications_qualifier, :provider_version_id) => nil
8+
def self.provider_matches(query_ids, qualifier)
9+
{
10+
qualify(qualifier, :provider_id) => query_ids.pacticipant_ids,
1411
}
12+
end
13+
14+
def self.provider_or_provider_version_matches_or_pact_unverified(query_ids, provider_version_qualifier = nil, provider_qualifier = nil)
15+
ors = provider_or_provider_version_criteria(query_ids, provider_version_qualifier, provider_qualifier)
16+
17+
# If we have specified any versions, then we need to add an
18+
# "OR (provider matches these IDs and provider version is null)"
19+
# so that we get a line with blank verification details.
20+
if query_ids.pacticipant_version_ids.any?
21+
ors << {
22+
qualify(provider_qualifier, :provider_id) => query_ids.all_pacticipant_ids,
23+
qualify(provider_version_qualifier, :provider_version_id) => nil
24+
}
25+
end
26+
1527
Sequel.|(*ors)
1628
end
1729

18-
def self.provider_or_provider_version_criteria(query_ids, qualifier = nil)
30+
def self.provider_or_provider_version_criteria(query_ids, provider_version_qualifier = nil, provider_qualifier = nil)
1931
ors = []
20-
ors << { qualify(qualifier, :provider_version_id) => query_ids.pacticipant_version_ids } if query_ids.pacticipant_version_ids.any?
21-
ors << { qualify(qualifier, :provider_id) => query_ids.pacticipant_ids } if query_ids.pacticipant_ids.any?
32+
ors << { qualify(provider_version_qualifier, :provider_version_id) => query_ids.pacticipant_version_ids } if query_ids.pacticipant_version_ids.any?
33+
ors << { qualify(provider_qualifier, :provider_id) => query_ids.pacticipant_ids } if query_ids.pacticipant_ids.any?
2234
ors
2335
end
2436

0 commit comments

Comments
 (0)