Skip to content

Commit a57ae0e

Browse files
authored
Merge pull request #534 from pact-foundation/feat/verifier-cli-retries
feat: add --retries / PACT_BROKER_HTTP_RETRIES to pact_verifier_cli
2 parents dea1bb2 + 27a6872 commit a57ae0e

11 files changed

Lines changed: 463 additions & 410 deletions

File tree

rust/Cargo.lock

Lines changed: 353 additions & 340 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/pact_ffi/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pact_matching = { version = "~2.0.3", path = "../pact_matching" }
3333
pact_mock_server = "~2.2.1"
3434
pact_models = { version = "~1.3.10" }
3535
pact-plugin-driver = { version = "~0.7.5" }
36-
pact_verifier = { version = "~1.3.5", path = "../pact_verifier" }
36+
pact_verifier = { version = "~1.4.0", path = "../pact_verifier" }
3737
panic-message = "0.3.0"
3838
rand = "0.9.2"
3939
rand_regex = "0.18.1"

rust/pact_verifier/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pact_verifier"
3-
version = "1.3.6"
3+
version = "1.4.0"
44
authors = ["Ronald Holshausen <ronald.holshausen@gmail.com>"]
55
edition = "2024"
66
description = "Pact-Rust support library that implements provider verification functions"

rust/pact_verifier/src/callback_executors.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub struct HttpRequestProviderStateExecutor {
9999
/// If state change request data should be sent in the body (true) or as query parameters (false)
100100
pub state_change_body: bool,
101101
/// Number of times to retry the provider state request, zero means none
102-
pub reties: u8
102+
pub retries: u8
103103
}
104104

105105
impl Default for HttpRequestProviderStateExecutor {
@@ -109,7 +109,7 @@ impl Default for HttpRequestProviderStateExecutor {
109109
state_change_url: None,
110110
state_change_teardown: false,
111111
state_change_body: true,
112-
reties: 3
112+
retries: 8
113113
}
114114
}
115115
}
@@ -153,7 +153,7 @@ impl ProviderStateExecutor for HttpRequestProviderStateExecutor {
153153
}
154154
state_change_request.query = Some(query);
155155
}
156-
make_state_change_request(client.unwrap_or(&reqwest::Client::default()), &state_change_url, &state_change_request, self.reties).await
156+
make_state_change_request(client.unwrap_or(&reqwest::Client::default()), &state_change_url, &state_change_request, self.retries).await
157157
.map_err(|err| ProviderStateError { description: err.to_string(), interaction_id }.into())
158158
},
159159
None => {

rust/pact_verifier/src/lib.rs

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,10 @@ pub struct VerificationOptions<F> where F: RequestFilterExecutor {
994994
/// Only execute the interactions that failed on the previous verifier run
995995
pub run_last_failed_only: bool,
996996
/// If redirects should be automatically followed
997-
pub follow_redirects: bool
997+
pub follow_redirects: bool,
998+
/// Number of times to retry failed HTTP requests to the Pact Broker
999+
/// (retries on 5xx, 408, and 429). Default is 8.
1000+
pub broker_request_retries: u8,
9981001
}
9991002

10001003
impl <F: RequestFilterExecutor> Default for VerificationOptions<F> {
@@ -1008,7 +1011,8 @@ impl <F: RequestFilterExecutor> Default for VerificationOptions<F> {
10081011
no_pacts_is_error: true,
10091012
exit_on_first_failure: false,
10101013
run_last_failed_only: false,
1011-
follow_redirects: true
1014+
follow_redirects: true,
1015+
broker_request_retries: 8,
10121016
}
10131017
}
10141018
}
@@ -1067,7 +1071,7 @@ pub async fn verify_provider_async<F: RequestFilterExecutor, S: ProviderStateExe
10671071
) -> anyhow::Result<VerificationExecutionResult> {
10681072
pact_matching::matchingrules::configure_core_catalogue();
10691073
async {
1070-
let pact_results = fetch_pacts(source, consumers, &provider_info).await;
1074+
let pact_results = fetch_pacts(source, consumers, &provider_info, verification_options.broker_request_retries).await;
10711075

10721076
let mut total_results = 0;
10731077
let mut pending_errors: Vec<(String, MismatchResult)> = vec![];
@@ -1167,7 +1171,7 @@ pub async fn verify_provider_async<F: RequestFilterExecutor, S: ProviderStateExe
11671171
}
11681172

11691173
if let Some(publish) = publish_options {
1170-
publish_result(results.as_slice(), &pact_source, &publish, metrics_data.as_ref()).await;
1174+
publish_result(results.as_slice(), &pact_source, &publish, metrics_data.as_ref(), verification_options.broker_request_retries).await;
11711175

11721176
if !errors.is_empty() || !pending_errors.is_empty() {
11731177
process_notices(&context, VERIFICATION_NOTICE_AFTER_ERROR_RESULT_AND_PUBLISH, &mut verification_result);
@@ -1296,7 +1300,8 @@ pub fn interaction_mismatch_output(
12961300
#[tracing::instrument(level = "trace")]
12971301
async fn fetch_pact(
12981302
source: PactSource,
1299-
provider: &ProviderInfo
1303+
provider: &ProviderInfo,
1304+
retries: u8,
13001305
) -> Vec<anyhow::Result<(Box<dyn Pact + Send + Sync + RefUnwindSafe>, Option<PactVerificationContext>, PactSource, Duration)>> {
13011306
trace!("fetch_pact(source={})", source);
13021307

@@ -1344,7 +1349,8 @@ async fn fetch_pact(
13441349
let result = timeit_async(pact_broker::fetch_pacts_from_broker(
13451350
broker_url.as_str(),
13461351
provider_name.as_str(),
1347-
auth.clone()
1352+
auth.clone(),
1353+
retries,
13481354
)).await;
13491355

13501356
match result {
@@ -1387,7 +1393,8 @@ async fn fetch_pact(
13871393
provider_tags.clone(),
13881394
provider_branch.clone(),
13891395
selectors.clone(),
1390-
auth.clone()
1396+
auth.clone(),
1397+
retries,
13911398
)).await;
13921399

13931400
match result {
@@ -1464,13 +1471,14 @@ fn is_pact_broker_source(links: &Vec<Link>) -> bool {
14641471
async fn fetch_pacts(
14651472
source: Vec<PactSource>,
14661473
consumers: Vec<String>,
1467-
provider: &ProviderInfo
1474+
provider: &ProviderInfo,
1475+
retries: u8,
14681476
) -> Vec<anyhow::Result<(Box<dyn Pact + Send + Sync + RefUnwindSafe>, Option<PactVerificationContext>, PactSource, Duration)>> {
14691477
trace!("fetch_pacts(source={}, consumers={:?})", source.iter().map(|s| s.to_string()).join(", "), consumers);
14701478

14711479
futures::stream::iter(source)
14721480
.then(|pact_source| async {
1473-
futures::stream::iter(fetch_pact(pact_source, provider).await)
1481+
futures::stream::iter(fetch_pact(pact_source, provider, retries).await)
14741482
})
14751483
.flatten()
14761484
.filter(|res| futures::future::ready(filter_consumers(&consumers, res)))
@@ -1675,18 +1683,19 @@ async fn publish_result(
16751683
results: &[VerificationInteractionResult],
16761684
source: &PactSource,
16771685
options: &PublishOptions,
1678-
metrics_data: Option<&VerificationMetrics>
1686+
metrics_data: Option<&VerificationMetrics>,
1687+
retries: u8,
16791688
) {
16801689
let publish_result = match source {
16811690
PactSource::BrokerUrl(_, broker_url, auth, links) => {
16821691
publish_to_broker(results, source, &options.build_url, &options.provider_tags,
16831692
&options.provider_branch, &options.provider_version, links.clone(), broker_url.clone(),
1684-
auth.clone(), metrics_data
1693+
auth.clone(), metrics_data, retries
16851694
).await
16861695
}
16871696
PactSource::BrokerWithDynamicConfiguration { broker_url, auth, links, provider_branch, provider_tags, .. } => {
16881697
publish_to_broker(results, source, &options.build_url, &provider_tags, &provider_branch,
1689-
&options.provider_version, links.clone(), broker_url.clone(), auth.clone(), metrics_data
1698+
&options.provider_version, links.clone(), broker_url.clone(), auth.clone(), metrics_data, retries
16901699
).await
16911700
}
16921701
_ => {
@@ -1710,7 +1719,8 @@ async fn publish_to_broker(
17101719
links: Vec<Link>,
17111720
broker_url: String,
17121721
auth: Option<HttpAuth>,
1713-
metrics_data: Option<&VerificationMetrics>
1722+
metrics_data: Option<&VerificationMetrics>,
1723+
retries: u8,
17141724
) -> Result<Value, pact_broker::PactBrokerError> {
17151725
info!("Publishing verification results back to the Pact Broker");
17161726
let result = if results.iter().all(|r| r.result.is_ok()) {
@@ -1733,7 +1743,8 @@ async fn publish_to_broker(
17331743
build_url.clone(),
17341744
provider_tags.clone(),
17351745
provider_branch.clone(),
1736-
metrics_data
1746+
metrics_data,
1747+
retries,
17371748
).await
17381749
}
17391750

0 commit comments

Comments
 (0)