Move Retry to core types.

This commit is contained in:
Jean-Christophe Amiel 2024-06-19 15:12:05 +02:00
parent b83741d9ef
commit bde10d3102
No known key found for this signature in database
GPG Key ID: 07FF11CFD55356CC
18 changed files with 74 additions and 52 deletions

View File

@ -1,7 +1,6 @@
name: retry
long: retry
value: NUM
value_default: 0
value_parser: clap::value_parser!(i32).range(-1..)
help: Maximum number of retries, 0 for no retries, -1 for unlimited retries
---

View File

@ -26,7 +26,7 @@ def main():
+ get_files("tests_failed/*." + extension)
+ get_files("tests_failed_not_linted/*." + extension)
+ get_files("tests_error_parser/*." + extension)
# + get_files("ssl/*." + extension)
+ get_files("ssl/*." + extension)
)
for f in sorted(script_files):
test_script.test(f)

View File

@ -108,7 +108,7 @@ Options:
--resolve <HOST:PORT:ADDR>
Provide a custom address for a specific HOST and PORT pair
--retry <NUM>
Maximum number of retries, 0 for no retries, -1 for unlimited retries [default: 0]
Maximum number of retries, 0 for no retries, -1 for unlimited retries
--retry-interval <MILLISECONDS>
Interval in milliseconds before a retry [default: 1000]
--ssl-no-revoke

View File

@ -450,7 +450,6 @@ pub fn retry() -> clap::Arg {
clap::Arg::new("retry")
.long("retry")
.value_name("NUM")
.default_value("0")
.value_parser(clap::value_parser!(i32).range(-1..))
.allow_hyphen_values(true)
.help("Maximum number of retries, 0 for no retries, -1 for unlimited retries")

View File

@ -24,7 +24,7 @@ use std::{env, fs, io};
use clap::ArgMatches;
use hurl::runner::{Input, Value};
use hurl_core::ast::Retry;
use hurl_core::typing::Retry;
use super::variables::{parse as parse_variable, parse_value};
use super::{CliOptionsError, Repeat};
@ -378,11 +378,11 @@ pub fn resolves(arg_matches: &ArgMatches) -> Vec<String> {
get_strings(arg_matches, "resolve").unwrap_or_default()
}
pub fn retry(arg_matches: &ArgMatches) -> Retry {
match get::<i32>(arg_matches, "retry").unwrap() {
-1 => Retry::Infinite,
0 => Retry::None,
r => Retry::Finite(r as usize),
pub fn retry(arg_matches: &ArgMatches) -> Option<Retry> {
match get::<i32>(arg_matches, "retry") {
Some(-1) => Some(Retry::Infinite),
Some(r) => Some(Retry::Finite(r as usize)),
None => None,
}
}

View File

@ -31,11 +31,12 @@ use hurl::http::RequestedHttpVersion;
use hurl::runner::{Input, Output};
use hurl::util::logger::{LoggerOptions, LoggerOptionsBuilder, Verbosity};
use hurl::util::path::ContextDir;
use hurl_core::ast::{Entry, Retry};
use hurl_core::ast::Entry;
use crate::cli;
use crate::runner::{RunnerOptions, RunnerOptionsBuilder, Value};
pub use error::CliOptionsError;
use hurl_core::typing::Retry;
/// Represents the list of all options that can be used in Hurl command line.
#[derive(Clone, Debug, PartialEq, Eq)]
@ -82,7 +83,7 @@ pub struct CliOptions {
pub proxy: Option<String>,
pub repeat: Option<Repeat>,
pub resolves: Vec<String>,
pub retry: Retry,
pub retry: Option<Retry>,
pub retry_interval: Duration,
pub ssl_no_revoke: bool,
pub tap_file: Option<PathBuf>,

View File

@ -22,10 +22,11 @@ use std::time::Instant;
use chrono::Utc;
use hurl_core::ast::VersionValue::VersionAnyLegacy;
use hurl_core::ast::{
Body, Bytes, Entry, MultilineString, OptionKind, Request, Response, Retry, SourceInfo,
Body, Bytes, Entry, MultilineString, OptionKind, Request, Response, SourceInfo,
};
use hurl_core::error::DisplaySourceError;
use hurl_core::parser;
use hurl_core::typing::Retry;
use crate::http::{Call, Client};
use crate::runner::event::EventListener;
@ -290,7 +291,7 @@ fn run_request(
let mut has_error = !result.errors.is_empty();
// The retry threshold can only be reached with a finite positive number of retries
let retry_max_reached = if let Retry::Finite(r) = options.retry {
let retry_max_reached = if let Some(Retry::Finite(r)) = options.retry {
retry_count > r
} else {
false
@ -306,7 +307,7 @@ fn run_request(
// We log eventual errors, only if we're not retrying the current entry...
// The retry does not take into account a possible output Error
let retry = !matches!(options.retry, Retry::None) && !retry_max_reached && has_error;
let retry = options.retry.is_some() && !retry_max_reached && has_error;
// When --output is overridden on a request level, we output the HTTP response only if the
// call has succeeded. Output errors are not taken into account for retrying requests.
@ -484,7 +485,11 @@ fn get_non_default_options(options: &RunnerOptions) -> Vec<(&'static str, String
}
if options.retry != default_options.retry {
non_default_options.push(("retry", options.retry.to_string()));
let value = match options.retry {
Some(retry) => retry.to_string(),
None => "none".to_string(),
};
non_default_options.push(("retry", value));
}
if options.unix_socket != default_options.unix_socket {

View File

@ -20,8 +20,9 @@ use std::time::Duration;
use hurl_core::ast::{
BooleanOption, Entry, EntryOption, Float, NaturalOption, Number as AstNumber, OptionKind,
Retry, RetryOption, SectionValue, VariableDefinition, VariableValue,
RetryOption, SectionValue, VariableDefinition, VariableValue,
};
use hurl_core::typing::Retry;
use crate::http::{IpResolve, RequestedHttpVersion};
use crate::runner::template::{eval_expression, eval_template};
@ -204,7 +205,7 @@ pub fn get_entry_options(
}
OptionKind::Retry(value) => {
let value = eval_retry_option(value, variables)?;
entry_options.retry = value;
entry_options.retry = Some(value);
}
OptionKind::RetryInterval(value) => {
let value = eval_natural_option(value, variables)?;
@ -356,9 +357,7 @@ fn eval_retry_option(
Value::Number(Number::Integer(value)) => {
if value == -1 {
Ok(Retry::Infinite)
} else if value == 0 {
Ok(Retry::None)
} else if value > 0 {
} else if value >= 0 {
Ok(Retry::Finite(value as usize))
} else {
let kind = RunnerErrorKind::TemplateVariableInvalidType {

View File

@ -17,7 +17,8 @@
*/
use std::time::Duration;
use hurl_core::ast::{Entry, Retry};
use hurl_core::ast::Entry;
use hurl_core::typing::Retry;
use crate::http::{IpResolve, RequestedHttpVersion};
use crate::runner::Output;
@ -54,7 +55,7 @@ pub struct RunnerOptionsBuilder {
pre_entry: Option<fn(Entry) -> bool>,
proxy: Option<String>,
resolves: Vec<String>,
retry: Retry,
retry: Option<Retry>,
retry_interval: Duration,
skip: bool,
ssl_no_revoke: bool,
@ -98,7 +99,7 @@ impl Default for RunnerOptionsBuilder {
pre_entry: None,
proxy: None,
resolves: vec![],
retry: Retry::None,
retry: None,
retry_interval: Duration::from_millis(1000),
skip: false,
ssl_no_revoke: false,
@ -327,7 +328,7 @@ impl RunnerOptionsBuilder {
/// Sets maximum number of retries.
///
/// Default is 0.
pub fn retry(&mut self, retry: Retry) -> &mut Self {
pub fn retry(&mut self, retry: Option<Retry>) -> &mut Self {
self.retry = retry;
self
}
@ -461,7 +462,7 @@ pub struct RunnerOptions {
pub(crate) pre_entry: Option<fn(Entry) -> bool>,
pub(crate) proxy: Option<String>,
pub(crate) resolves: Vec<String>,
pub(crate) retry: Retry,
pub(crate) retry: Option<Retry>,
pub(crate) retry_interval: Duration,
pub(crate) skip: bool,
pub(crate) ssl_no_revoke: bool,

View File

@ -24,7 +24,6 @@ use hurl::runner;
use hurl::runner::{EntryResult, HurlResult, RunnerOptionsBuilder};
use hurl::util::logger::LoggerOptionsBuilder;
use hurl::util::path::ContextDir;
use hurl_core::ast::Retry;
#[test]
fn simple_sample() {
@ -117,7 +116,7 @@ fn simple_sample() {
.post_entry(None)
.pre_entry(None)
.proxy(None)
.retry(Retry::None)
.retry(None)
.retry_interval(Duration::from_secs(1))
.timeout(Duration::from_secs(300))
.to_entry(None)

View File

@ -16,6 +16,7 @@
*
*/
use crate::ast::json;
use crate::typing::Retry;
///
/// Hurl AST
@ -915,10 +916,3 @@ pub enum FilterValue {
expr: Template,
},
}
#[derive(Clone, Debug, PartialEq, Eq, Copy)]
pub enum Retry {
None,
Finite(usize),
Infinite,
}

View File

@ -278,17 +278,6 @@ impl PredicateFuncValue {
}
}
impl fmt::Display for Retry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
Retry::None => 0,
Retry::Finite(n) => *n as i32,
Retry::Infinite => -1,
};
write!(f, "{}", value)
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -18,6 +18,7 @@
use std::fmt::Display;
use crate::ast::*;
use crate::typing::Retry;
/// Returns an HTML string of the Hurl file `hurl_file`.
///
@ -262,7 +263,6 @@ impl HtmlFormatter {
match retry {
Retry::Finite(n) => self.fmt_number(n),
Retry::Infinite => self.fmt_number(-1),
Retry::None => self.fmt_number(0),
};
}

View File

@ -20,3 +20,4 @@ pub mod error;
pub mod format;
pub mod parser;
pub mod text;
pub mod typing;

View File

@ -23,6 +23,7 @@ use crate::parser::primitives::*;
use crate::parser::reader::Reader;
use crate::parser::string::*;
use crate::parser::{expr, filename, filename_password, ParseResult};
use crate::typing::Retry;
/// Parse an option in an `[Options]` section.
pub fn parse(reader: &mut Reader) -> ParseResult<EntryOption> {
@ -255,9 +256,7 @@ fn retry(reader: &mut Reader) -> ParseResult<Retry> {
let value = nonrecover(integer, reader)?;
if value == -1 {
Ok(Retry::Infinite)
} else if value == 0 {
Ok(Retry::None)
} else if value > 0 {
} else if value >= 0 {
Ok(Retry::Finite(value as usize))
} else {
let kind = ParseErrorKind::Expecting {

View File

@ -0,0 +1,36 @@
/*
* Hurl (https://hurl.dev)
* Copyright (C) 2024 Orange
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
use core::fmt;
/// Represents a retry operation, either finite or infinite.
#[derive(Clone, Debug, PartialEq, Eq, Copy)]
pub enum Retry {
Finite(usize),
Infinite,
}
impl fmt::Display for Retry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
Retry::Finite(n) => *n as i32,
Retry::Infinite => -1,
};
write!(f, "{}", value)
}
}

View File

@ -18,6 +18,7 @@
use base64::engine::general_purpose;
use base64::Engine;
use hurl_core::ast::*;
use hurl_core::typing::Retry;
use super::serialize_json::*;
@ -363,7 +364,6 @@ impl ToJson for RetryOption {
impl ToJson for Retry {
fn to_json(&self) -> JValue {
match self {
Retry::None => JValue::Number("0".to_string()),
Retry::Finite(value) => JValue::Number(value.to_string()),
Retry::Infinite => JValue::Number("-1".to_string()),
}

View File

@ -16,6 +16,7 @@
*
*/
use hurl_core::ast::*;
use hurl_core::typing::Retry;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Token {
@ -945,7 +946,6 @@ impl Tokenizable for RetryOption {
impl Tokenizable for Retry {
fn tokenize(&self) -> Vec<Token> {
match self {
Retry::None => vec![Token::Number("0".to_string())],
Retry::Finite(n) => vec![Token::Number(n.to_string())],
Retry::Infinite => vec![Token::Number("-1".to_string())],
}