Skip to content

Commit

Permalink
feat: optimise matrix query when selectors with pacticipant names onl…
Browse files Browse the repository at this point in the history
…y are used
  • Loading branch information
bethesque committed Sep 4, 2023
1 parent 923c0d2 commit b98f5d1
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 10 deletions.
46 changes: 41 additions & 5 deletions lib/pact_broker/matrix/matrix_row_dataset_module.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,52 @@ def matching_only_selectors_joining_verifications(resolved_selectors)
.where(consumer_id: specified_pacticipant_ids).or(provider_id: specified_pacticipant_ids)
end

# Return pact publications where the consumer version is described by any of the resolved_selectors, AND the provider is described by any of the resolved selectors.
# Return pact publications where the consumer/consumer version is described by any of the resolved_selectors, AND the provider is described by any of the resolved selectors.
# @private
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
# @return [Sequel::Dataset<MatrixRow>]
def matching_only_selectors_as_consumer(resolved_selectors)
pacticipant_ids = resolved_selectors.collect(&:pacticipant_id).uniq
[
matching_only_selectors_as_consumer_where_only_pacticipant_name_in_selector(resolved_selectors),
matching_only_selectors_as_consumer_where_not_only_pacticipant_name_in_selector(resolved_selectors),
].compact.reduce(&:union)
end

select_pact_columns_with_aliases
.inner_join_versions_for_selectors_as_consumer(resolved_selectors)
.where(provider_id: pacticipant_ids)

# Return pact publications where the consumer is described by any of the resolved_selectors *that only specify the pacticipant NAME*, AND the provider is described by any of the resolved selectors.
# If the original selector only specified the pacticipant name, we don't need to join to the versions table to identify the required pact_publications.
# Return nil if there are no resolved selectors where only the pacticipant name is specified.
# @private
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
# @return [Sequel::Dataset<MatrixRow>, nil]
def matching_only_selectors_as_consumer_where_only_pacticipant_name_in_selector(resolved_selectors)
all_pacticipant_ids = resolved_selectors.collect(&:pacticipant_id).uniq
pacticipant_ids_for_pacticipant_only_selectors = resolved_selectors.select(&:only_pacticipant_name_specified?).collect(&:pacticipant_id).uniq

if pacticipant_ids_for_pacticipant_only_selectors.any?
select_pact_columns_with_aliases
.where(consumer_id: pacticipant_ids_for_pacticipant_only_selectors)
.where(provider_id: all_pacticipant_ids)
end
end

# Return pact publications where the consumer *version* is described by any of the resolved_selectors
# *that specify more than just the pacticipant name*,
# AND the provider is described by any of the resolved selectors.
# If the selector uses any of the tag/branch/environment/latest attributes, we need to join to the versions table to identify the required pact_publications.
# Return nil if there are no resolved selectors where anything other than the pacticipant name is specified.
# @private
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
# @return [Sequel::Dataset<MatrixRow>, nil]
def matching_only_selectors_as_consumer_where_not_only_pacticipant_name_in_selector(resolved_selectors)
all_pacticipant_ids = resolved_selectors.collect(&:pacticipant_id).uniq
resolved_selectors_with_versions_specified = resolved_selectors.reject(&:only_pacticipant_name_specified?)

if resolved_selectors_with_versions_specified.any?
select_pact_columns_with_aliases
.inner_join_versions_for_selectors_as_consumer(resolved_selectors_with_versions_specified)
.where(provider_id: all_pacticipant_ids)
end
end

# @private
Expand Down
53 changes: 48 additions & 5 deletions lib/pact_broker/matrix/matrix_row_verification_dataset_module.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,62 @@ module MatrixRowVerificationDatasetModule
# @param [Array<PactBroker::Matrix::ResolvedSelector>] selectors
# @return [Sequel::Dataset<MatrixRow>]
def matching_only_selectors_as_provider(resolved_selectors)
# get the UnresolvedSelector objects back out of the resolved_selectors because the Version.for_selector() method uses the UnresolvedSelector
pacticipant_ids = resolved_selectors.collect(&:pacticipant_id).uniq
select_verification_columns_with_aliases
.inner_join_versions_for_selectors_as_provider(resolved_selectors)
.where(consumer_id: pacticipant_ids)
[
matching_only_selectors_as_provider_where_only_pacticipant_name_in_selector(resolved_selectors),
matching_only_selectors_as_provider_where_not_only_pacticipant_name_in_selector(resolved_selectors)
].compact.reduce(&:union)
end

# @public
# @return [Sequel::Dataset<Verification>, nil]
def matching_selectors_as_provider_for_any_consumer(resolved_selectors)
select_verification_columns_with_aliases
.inner_join_versions_for_selectors_as_provider(resolved_selectors)
end

# Return verifications where the provider is described by any of the resolved_selectors *that only specify the pacticipant NAME*,
# AND the consumer is described by any of the resolved selectors.
# If the original selector only specified the pacticipant name, we don't need to join to the versions table to identify the required verifications.
# Return nil if there are no resolved selectors where only the pacticipant name is specified.
# @private
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
# @return [Sequel::Dataset<Verification>, nil]
def matching_only_selectors_as_provider_where_only_pacticipant_name_in_selector(resolved_selectors)
all_pacticipant_ids = resolved_selectors.collect(&:pacticipant_id).uniq
pacticipant_ids_for_pacticipant_only_selectors = resolved_selectors.select(&:only_pacticipant_name_specified?).collect(&:pacticipant_id).uniq

if pacticipant_ids_for_pacticipant_only_selectors.any?
select_verification_columns_with_aliases
.where(provider_id: pacticipant_ids_for_pacticipant_only_selectors)
.where(consumer_id: all_pacticipant_ids)
end
end

# Return verifications where the provider *version* is described by any of the resolved_selectors
# *that specify more than just the pacticipant name*,
# AND the consumer is described by any of the resolved selectors.
# If the selector uses any of the tag/branch/environment/latest attributes, we need to join to the versions table to identify the required verifications.
# Return nil if there are no resolved selectors where anything other than the pacticipant name is specified.
# @private
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
# @return [Sequel::Dataset<Verification>, nil]
def matching_only_selectors_as_provider_where_not_only_pacticipant_name_in_selector(resolved_selectors)
# get the UnresolvedSelector objects back out of the resolved_selectors because the Version.for_selector() method uses the UnresolvedSelector
all_pacticipant_ids = resolved_selectors.collect(&:pacticipant_id).uniq
resolved_selectors_with_versions_specified = resolved_selectors.reject(&:only_pacticipant_name_specified?)

if resolved_selectors_with_versions_specified.any?
select_verification_columns_with_aliases
.inner_join_versions_for_selectors_as_provider(resolved_selectors_with_versions_specified)
.where(consumer_id: all_pacticipant_ids)
end
end

# Don't think it's worth splitting this into 2 different queries for selectors with only pacticipant name/selectors with version properties,
# as it's unlikely for there ever to be a query through the UI or CLI that results in 1 selector which only has a pacticipant name in it.
# @private
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
# @return [Sequel::Dataset<Verification>]
def inner_join_versions_for_selectors_as_provider(resolved_selectors)
# get the UnresolvedSelector objects back out of the resolved_selectors because the Version.for_selector() method uses the UnresolvedSelector
unresolved_selectors = resolved_selectors.collect(&:original_selector).uniq
Expand Down

0 comments on commit b98f5d1

Please sign in to comment.