Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
693 changes: 353 additions & 340 deletions rust/Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion rust/pact_ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pact_matching = { version = "~2.0.3", path = "../pact_matching" }
pact_mock_server = "~2.2.1"
pact_models = { version = "~1.3.10" }
pact-plugin-driver = { version = "~0.7.5" }
pact_verifier = { version = "~1.3.5", path = "../pact_verifier" }
pact_verifier = { version = "~1.4.0", path = "../pact_verifier" }
panic-message = "0.3.0"
rand = "0.9.2"
rand_regex = "0.18.1"
Expand Down
2 changes: 1 addition & 1 deletion rust/pact_verifier/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pact_verifier"
version = "1.3.6"
version = "1.4.0"
authors = ["Ronald Holshausen <ronald.holshausen@gmail.com>"]
edition = "2024"
description = "Pact-Rust support library that implements provider verification functions"
Expand Down
6 changes: 3 additions & 3 deletions rust/pact_verifier/src/callback_executors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub struct HttpRequestProviderStateExecutor {
/// If state change request data should be sent in the body (true) or as query parameters (false)
pub state_change_body: bool,
/// Number of times to retry the provider state request, zero means none
pub reties: u8
pub retries: u8
}

impl Default for HttpRequestProviderStateExecutor {
Expand All @@ -109,7 +109,7 @@ impl Default for HttpRequestProviderStateExecutor {
state_change_url: None,
state_change_teardown: false,
state_change_body: true,
reties: 3
retries: 8
}
}
}
Expand Down Expand Up @@ -153,7 +153,7 @@ impl ProviderStateExecutor for HttpRequestProviderStateExecutor {
}
state_change_request.query = Some(query);
}
make_state_change_request(client.unwrap_or(&reqwest::Client::default()), &state_change_url, &state_change_request, self.reties).await
make_state_change_request(client.unwrap_or(&reqwest::Client::default()), &state_change_url, &state_change_request, self.retries).await
.map_err(|err| ProviderStateError { description: err.to_string(), interaction_id }.into())
},
None => {
Expand Down
39 changes: 25 additions & 14 deletions rust/pact_verifier/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,10 @@ pub struct VerificationOptions<F> where F: RequestFilterExecutor {
/// Only execute the interactions that failed on the previous verifier run
pub run_last_failed_only: bool,
/// If redirects should be automatically followed
pub follow_redirects: bool
pub follow_redirects: bool,
/// Number of times to retry failed HTTP requests to the Pact Broker
/// (retries on 5xx, 408, and 429). Default is 8.
pub broker_request_retries: u8,
}

impl <F: RequestFilterExecutor> Default for VerificationOptions<F> {
Expand All @@ -1008,7 +1011,8 @@ impl <F: RequestFilterExecutor> Default for VerificationOptions<F> {
no_pacts_is_error: true,
exit_on_first_failure: false,
run_last_failed_only: false,
follow_redirects: true
follow_redirects: true,
broker_request_retries: 8,
}
}
}
Expand Down Expand Up @@ -1067,7 +1071,7 @@ pub async fn verify_provider_async<F: RequestFilterExecutor, S: ProviderStateExe
) -> anyhow::Result<VerificationExecutionResult> {
pact_matching::matchingrules::configure_core_catalogue();
async {
let pact_results = fetch_pacts(source, consumers, &provider_info).await;
let pact_results = fetch_pacts(source, consumers, &provider_info, verification_options.broker_request_retries).await;

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

if let Some(publish) = publish_options {
publish_result(results.as_slice(), &pact_source, &publish, metrics_data.as_ref()).await;
publish_result(results.as_slice(), &pact_source, &publish, metrics_data.as_ref(), verification_options.broker_request_retries).await;

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

Expand Down Expand Up @@ -1344,7 +1349,8 @@ async fn fetch_pact(
let result = timeit_async(pact_broker::fetch_pacts_from_broker(
broker_url.as_str(),
provider_name.as_str(),
auth.clone()
auth.clone(),
retries,
)).await;

match result {
Expand Down Expand Up @@ -1387,7 +1393,8 @@ async fn fetch_pact(
provider_tags.clone(),
provider_branch.clone(),
selectors.clone(),
auth.clone()
auth.clone(),
retries,
)).await;

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

futures::stream::iter(source)
.then(|pact_source| async {
futures::stream::iter(fetch_pact(pact_source, provider).await)
futures::stream::iter(fetch_pact(pact_source, provider, retries).await)
})
.flatten()
.filter(|res| futures::future::ready(filter_consumers(&consumers, res)))
Expand Down Expand Up @@ -1675,18 +1683,19 @@ async fn publish_result(
results: &[VerificationInteractionResult],
source: &PactSource,
options: &PublishOptions,
metrics_data: Option<&VerificationMetrics>
metrics_data: Option<&VerificationMetrics>,
retries: u8,
) {
let publish_result = match source {
PactSource::BrokerUrl(_, broker_url, auth, links) => {
publish_to_broker(results, source, &options.build_url, &options.provider_tags,
&options.provider_branch, &options.provider_version, links.clone(), broker_url.clone(),
auth.clone(), metrics_data
auth.clone(), metrics_data, retries
).await
}
PactSource::BrokerWithDynamicConfiguration { broker_url, auth, links, provider_branch, provider_tags, .. } => {
publish_to_broker(results, source, &options.build_url, &provider_tags, &provider_branch,
&options.provider_version, links.clone(), broker_url.clone(), auth.clone(), metrics_data
&options.provider_version, links.clone(), broker_url.clone(), auth.clone(), metrics_data, retries
).await
}
_ => {
Expand All @@ -1710,7 +1719,8 @@ async fn publish_to_broker(
links: Vec<Link>,
broker_url: String,
auth: Option<HttpAuth>,
metrics_data: Option<&VerificationMetrics>
metrics_data: Option<&VerificationMetrics>,
retries: u8,
) -> Result<Value, pact_broker::PactBrokerError> {
info!("Publishing verification results back to the Pact Broker");
let result = if results.iter().all(|r| r.result.is_ok()) {
Expand All @@ -1733,7 +1743,8 @@ async fn publish_to_broker(
build_url.clone(),
provider_tags.clone(),
provider_branch.clone(),
metrics_data
metrics_data,
retries,
).await
}

Expand Down
Loading
Loading