Skip to content

Commit 34741da

Browse files
pahninPhanindra Srungavarapu
andauthored
feat: added has_messages column to pact_versions table (#880)
* feat: added has_messages column to pact_versions table * Added Interactins::Types to detect message types in interactions * Updated code to save has_messages correctly * Added database migrations for adding the column, backfilling the column in a batched manner to avoid issues Jira Ticket: [PACT-5319] * test: fix failing tests Jira Ticket: [PACT-5319] * chore: match the conten length Jira Ticket: [PACT-5319] --------- Co-authored-by: Phanindra Srungavarapu <[email protected]>
1 parent 30029d2 commit 34741da

File tree

11 files changed

+511
-10
lines changed

11 files changed

+511
-10
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Sequel.migration do
2+
change do
3+
alter_table(:pact_versions) do
4+
add_column(:has_messages, TrueClass, default: false, null: false)
5+
end
6+
end
7+
end
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
require "pact_broker/pacts/content"
2+
require "pact_broker/pacts/interactions/types"
3+
4+
Sequel.migration do
5+
up do
6+
batch_size = 500
7+
offset = 0
8+
9+
loop do
10+
rows = from(:pact_versions).order(:id).limit(batch_size).offset(offset).all
11+
break if rows.empty?
12+
13+
rows.each do |row|
14+
content = PactBroker::Pacts::Content.from_json(row[:content])
15+
has_messages = PactBroker::Pacts::Interactions::Types.for(content).has_messages?
16+
17+
from(:pact_versions)
18+
.where(id: row[:id])
19+
.update(has_messages: has_messages)
20+
end
21+
22+
offset += batch_size
23+
end
24+
end
25+
26+
down do
27+
28+
end
29+
end
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
module PactBroker
2+
module Pacts
3+
module Interactions
4+
class Types
5+
# Pact Spec v4+ message interaction types
6+
MESSAGE_TYPES = [
7+
"Asynchronous/Messages",
8+
"Synchronous/Messages"
9+
].freeze
10+
11+
def initialize(content)
12+
@content = content
13+
end
14+
15+
def self.for(content)
16+
new(content)
17+
end
18+
19+
def has_messages?
20+
if spec_version < 4.0
21+
# Pre-v4: messages in "messages" key
22+
content.messages&.any? || false
23+
else
24+
# V4+: messages are typed interactions
25+
content.interactions&.any? { |i| message_interaction?(i) } || false
26+
end
27+
end
28+
29+
private
30+
31+
attr_reader :content
32+
33+
def message_interaction?(interaction)
34+
interaction.is_a?(Hash) &&
35+
MESSAGE_TYPES.include?(interaction["type"])
36+
end
37+
38+
def spec_version
39+
content.pact_specification_version.to_f
40+
end
41+
end
42+
end
43+
end
44+
end

lib/pact_broker/pacts/repository.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
require "pact_broker/feature_toggle"
1515
require "pact_broker/pacts/pacts_for_verification_repository"
1616
require "pact_broker/pacts/content"
17+
require "pact_broker/pacts/interactions/types"
1718
require "pact_broker/policies"
1819

1920
module PactBroker
@@ -394,14 +395,16 @@ def find_or_create_pact_version consumer_id, provider_id, pact_version_sha, json
394395
end
395396

396397
def create_pact_version consumer_id, provider_id, sha, json_content
398+
content = Content.from_json(json_content)
397399
PactBroker::Pacts::PactVersion.new(
398400
consumer_id: consumer_id,
399401
provider_id: provider_id,
400402
sha: sha,
401403
content: json_content,
402404
created_at: Sequel.datetime_class.now,
403-
interactions_count: Content.from_json(json_content).interactions&.count || 0,
404-
messages_count: Content.from_json(json_content).messages&.count || 0
405+
interactions_count: content.interactions&.count || 0,
406+
messages_count: content.messages&.count || 0,
407+
has_messages: Interactions::Types.for(content).has_messages?
405408
).upsert
406409
end
407410

lib/pact_broker/test/test_data_builder.rb

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,9 @@ def create_verification parameters = {}
456456
parameters = default_parameters.merge(parameters)
457457
parameters.delete(:provider_version)
458458
verification = PactBroker::Domain::Verification.new(parameters)
459+
if pact.nil?
460+
@pact = find_pact(@consumer.name, @consumer_version.number, @provider.name)
461+
end
459462
pact_version = PactBroker::Pacts::Repository.new.find_pact_version(@consumer, @provider, pact.pact_version_sha)
460463
@provider_version = version_repository.find_by_pacticipant_id_and_number_or_create(provider.id, provider_version_number)
461464
branch_version = PactBroker::Versions::BranchVersionRepository.new.add_branch(@provider_version, branch) if branch
@@ -714,13 +717,16 @@ def set_created_at_if_set created_at, table_name, selector, date_column_name = :
714717
def default_json_content
715718
{
716719
"consumer" => {
717-
"name" => consumer.name
718-
},
719-
"provider" => {
720-
"name" => provider.name
721-
},
722-
"interactions" => [],
723-
"random" => rand
720+
"name" => consumer.name
721+
},
722+
"provider" => {
723+
"name" => provider.name
724+
},
725+
"interactions" => [],
726+
"metadata" => {
727+
"pactSpecification": { "version": "4.0" }
728+
},
729+
"random" => rand
724730
}.to_json
725731
end
726732

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"request": {
3+
"path": "/pacts/provider/Provider/for-verification",
4+
"headers": {
5+
"Content-Type": "application/json",
6+
"Accept": "application/hal+json"
7+
},
8+
"body": {
9+
"consumerVersionSelectors": [
10+
{
11+
"tag": "prod",
12+
"latest": true
13+
}
14+
],
15+
"includePendingStatus": false,
16+
"providerVersionTags": [
17+
"main"
18+
]
19+
}
20+
},
21+
"response": {
22+
"status": 200,
23+
"headers": {
24+
"content-type": "application/hal+json;charset=utf-8",
25+
"content-length": "840",
26+
"date": "<date>",
27+
"server": "Webmachine-Ruby/2.0.1 Rack/3.2"
28+
},
29+
"body": {
30+
"_embedded": {
31+
"pacts": [
32+
{
33+
"shortDescription": "latest with tag prod",
34+
"verificationProperties": {
35+
"notices": [
36+
{
37+
"when": "before_verification",
38+
"text": "The pact at http://example.org/pacts/provider/Provider/consumer/Consumer%202/pact-version/0f22f551a422b027066db7635cad8bd8a59ac869 is being verified because the pact content belongs to the consumer version matching the following criterion:\n * latest version tagged 'prod' (4.5.6)"
39+
}
40+
]
41+
},
42+
"_links": {
43+
"self": {
44+
"href": "http://example.org/pacts/provider/Provider/consumer/Consumer%202/pact-version/0f22f551a422b027066db7635cad8bd8a59ac869/metadata/cyU1QiU1RCU1QnQlNUQ9cHJvZCZzJTVCJTVEJTVCbCU1RD10cnVlJnMlNUIlNUQlNUJjdiU1RD0y",
45+
"name": "Pact between Consumer 2 (4.5.6) and Provider"
46+
}
47+
}
48+
}
49+
]
50+
},
51+
"_links": {
52+
"self": {
53+
"href": "http://example.org/pacts/provider/Provider/for-verification",
54+
"title": "Pacts to be verified"
55+
}
56+
}
57+
}
58+
}
59+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
{
2+
"consumer": { "name": "Foo" },
3+
"interactions": [
4+
{
5+
"_id": "5d6f8d633693c2391ba8fff297444b3ef1ccd00b",
6+
"contents": {
7+
"content": { "id": 1, "name": "drover", "type": "bulldog" },
8+
"contentType": "application/json",
9+
"encoded": false
10+
},
11+
"description": "a request for a dog",
12+
"matchingRules": {
13+
"body": {
14+
"$.id": { "combine": "AND", "matchers": [{ "match": "type" }] },
15+
"$.name": { "combine": "AND", "matchers": [{ "match": "type" }] },
16+
"$.type": {
17+
"combine": "AND",
18+
"matchers": [{ "match": "regex", "regex": "^(bulldog|sheepdog)$" }]
19+
}
20+
}
21+
},
22+
"metadata": { "queue": "animals" },
23+
"pending": false,
24+
"providerStates": [{ "name": "a dog named drover" }],
25+
"type": "Asynchronous/Messages"
26+
},
27+
{
28+
"_id": "a2cac63edba504277c1063f36620549785d78981",
29+
"description": "a request to get a product",
30+
"pending": false,
31+
"providerStates": [{ "name": "a product with ID 10 exists" }],
32+
"request": {
33+
"headers": { "Authorization": ["Bearer 2019-01-14T11:34:18.045Z"] },
34+
"matchingRules": {
35+
"header": {
36+
"$.Authorization[0]": {
37+
"combine": "AND",
38+
"matchers": [{ "match": "type" }]
39+
}
40+
}
41+
},
42+
"method": "GET",
43+
"path": "/product/10"
44+
},
45+
"response": {
46+
"body": {
47+
"content": {
48+
"id": "10",
49+
"name": "28 Degrees",
50+
"type": "CREDIT_CARD"
51+
},
52+
"contentType": "application/json",
53+
"encoded": false
54+
},
55+
"headers": { "Content-Type": ["application/json; charset=utf-8"] },
56+
"matchingRules": {
57+
"body": {
58+
"$": { "combine": "AND", "matchers": [{ "match": "type" }] }
59+
}
60+
},
61+
"status": 200
62+
},
63+
"type": "Synchronous/HTTP"
64+
}
65+
],
66+
"metadata": {
67+
"pact-js": { "version": "15.0.1" },
68+
"pactRust": { "ffi": "0.4.22", "models": "1.3.7" },
69+
"pactSpecification": { "version": "4.0" }
70+
},
71+
"provider": { "name": "Bar" }
72+
}

spec/lib/pact_broker/pacts/content_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,4 +486,4 @@ module Pacts
486486
end
487487
end
488488
end
489-
end
489+
end

0 commit comments

Comments
 (0)