Skip to content

Override Config aws-smithy-client  #567

@ymwjbxxq

Description

@ymwjbxxq

Describe the feature

Hi all,

as a follow-up of this issue #558
where we can set the timeout for the client to be latency aware with the retries

#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt()
        .with_ansi(false)
        .without_time()
        .with_max_level(tracing_subscriber::filter::LevelFilter::DEBUG)
        .init();

    let timeout_config = timeout::Config::new()
        .with_api_timeouts(
            timeout::Api::new()
                .with_call_timeout(TriState::Set(Duration::from_millis(150)))
                .with_call_attempt_timeout(TriState::Set(Duration::from_millis(50))),
        );
    let config = aws_config::from_env()
        .retry_config(RetryConfig::new().with_max_attempts(3))
        .timeout_config(timeout_config)

        .load()
        .await;

    let dynamodb_client = aws_sdk_dynamodb::Client::new(&config);

I have noticed the following:

DEBUG aws_smithy_client::retry: attempt 1 failed with Error(TransientError); retrying after 435.692227ms

And the aws-smithy-client/src/retry.rs is configured as:

const MAX_ATTEMPTS: u32 = 3;
const INITIAL_RETRY_TOKENS: usize = 500;
const RETRY_COST: usize = 5;

And I have no way to overwrite the default parameters.

From the test, I cannot get exactly where the initial value of the backoff is coming from
https://github.com/awslabs/smithy-rs/blob/a0539e20b069a7de021c84521d8f3c7ba098ad6d/rust-runtime/aws-smithy-client/src/retry.rs#L276

It seems to me that this line of code is not correct:

let backoff = b * (r.pow(self.local.attempts - 1) as f64);
let backoff = Duration::from_secs_f64(backoff).min(self.config.max_backoff);

Because:

  1. it does not consider a value to calculate the retry
  2. convert all in seconds with a max of 20s

It should be based on milliseconds https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7deed195b0811c97887dbcd6c98f1a6e

let exponential_delay = (ms * (r.pow(attempts - 1) as f64)) as u64;
let backoff =  Duration::from_millis(exponential_delay).min(Duration::from_secs(20));

If we can pass the backoff value it could become

let retry_config = RetryConfig::new()
  .with_max_attempts(5);
  .with_backoff_delay(100); //ms

Use Case

When you are latency aware, you should be able to overwrite the default parameters to configure the backoff.

In my configuration case, I have the following:

  • 3 retries
  • 50ms a for a single attempt
  • overall duration 150ms

the back-off moves the second retry after 435.692227ms
DEBUG aws_smithy_client::retry: attempt 1 failed with Error(TransientError); retrying after 435.692227ms

This means that it will never retry a second time.

Proposed Solution

Be able to overwrite the backoff policy.

If I wish to have this configuration

  • 3 retries
  • 50ms a for a single attempt

I could setup the backoff policy at 10ms. For example, I would have the following after the first failed attempt.

Retry 1 -> retrying after 20ms
Retry 2 -> retrying after 40ms
Retry 3 -> retrying after 60ms

Now I can setup my overall duration "with_call_timeout" to 210ms, giving the retries time to happen.

Other Information

No response

Acknowledgements

  • I may be able to implement this feature request
  • This feature might incur a breaking change

A note for the community

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue, please leave a comment

Metadata

Metadata

Assignees

Labels

feature-requestA feature should be added or improved.

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions