diff --git a/include/aws/io/retry_strategy.h b/include/aws/io/retry_strategy.h index 3d63c35e6..bc15580eb 100644 --- a/include/aws/io/retry_strategy.h +++ b/include/aws/io/retry_strategy.h @@ -106,14 +106,16 @@ enum aws_exponential_backoff_jitter_mode { * "use defaults" */ struct aws_exponential_backoff_retry_options { - /** Event loop group to use for scheduling tasks. */ + /* Event loop group to use for scheduling tasks. */ struct aws_event_loop_group *el_group; - /** Max retries to allow. The default value is 10 */ + /* Max retries to allow. The default value is 10 */ size_t max_retries; - /** Scaling factor to add for the backoff. Default is 500ms */ + /* Scaling factor to add for the backoff. Default is 500ms */ uint32_t backoff_scale_factor_ms; - /** Max retry backoff in seconds. Default is 20 seconds */ + /* Max retry backoff in seconds. Default is 20 seconds */ uint32_t max_backoff_secs; + /* Sets max_retries to 0 to disable retries altogether */ + bool no_retries; /** Jitter mode to use, see comments for aws_exponential_backoff_jitter_mode. * Default is AWS_EXPONENTIAL_BACKOFF_JITTER_DEFAULT */ enum aws_exponential_backoff_jitter_mode jitter_mode; diff --git a/source/exponential_backoff_retry_strategy.c b/source/exponential_backoff_retry_strategy.c index cf2472269..9cd6badec 100644 --- a/source/exponential_backoff_retry_strategy.c +++ b/source/exponential_backoff_retry_strategy.c @@ -27,6 +27,7 @@ struct exponential_backoff_retry_token { size_t max_retries; uint64_t backoff_scale_factor_ns; uint64_t maximum_backoff_ns; + bool no_retries; enum aws_exponential_backoff_jitter_mode jitter_mode; /* Let's not make this worse by constantly moving across threads if we can help it */ struct aws_event_loop *bound_loop; @@ -115,6 +116,10 @@ static int s_exponential_retry_acquire_token( (void)partition_id; /* no resource contention here so no timeouts. */ (void)timeout_ms; + struct exponential_backoff_strategy *exponential_backoff_strategy = retry_strategy->impl; + if(exponential_backoff_strategy->config.no_retries) { + return aws_raise_error(AWS_IO_RETRY_PERMISSION_DENIED); + } struct exponential_backoff_retry_token *backoff_retry_token = aws_mem_calloc(retry_strategy->allocator, 1, sizeof(struct exponential_backoff_retry_token)); @@ -135,7 +140,6 @@ static int s_exponential_retry_acquire_token( aws_retry_strategy_acquire(retry_strategy); backoff_retry_token->base.impl = backoff_retry_token; - struct exponential_backoff_strategy *exponential_backoff_strategy = retry_strategy->impl; backoff_retry_token->bound_loop = aws_event_loop_group_get_next_loop(exponential_backoff_strategy->config.el_group); backoff_retry_token->max_retries = exponential_backoff_strategy->config.max_retries; backoff_retry_token->backoff_scale_factor_ns = aws_timestamp_convert( diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fbcd3088c..1ed0ca67f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -316,6 +316,7 @@ add_test_case(test_exponential_backoff_retry_client_errors_do_not_count) add_test_case(test_exponential_backoff_retry_no_jitter_time_taken) add_test_case(test_exponential_max_backoff_retry_no_jitter) add_test_case(test_exponential_backoff_retry_invalid_options) +add_test_case(test_exponential_backoff_no_retries) add_test_case(test_standard_retry_strategy_setup_shutdown) add_test_case(test_standard_retry_strategy_failure_exhausts_bucket) diff --git a/tests/exponential_backoff_retry_test.c b/tests/exponential_backoff_retry_test.c index a3bf7bde0..cb65ca97c 100644 --- a/tests/exponential_backoff_retry_test.c +++ b/tests/exponential_backoff_retry_test.c @@ -327,3 +327,44 @@ static int s_test_exponential_backoff_retry_invalid_options_fn(struct aws_alloca return AWS_OP_SUCCESS; } AWS_TEST_CASE(test_exponential_backoff_retry_invalid_options, s_test_exponential_backoff_retry_invalid_options_fn) + +static int s_test_exponential_backoff_no_retries_fn( + struct aws_allocator *allocator, void *ctx) { + (void)ctx; + + aws_io_library_init(allocator); + + struct aws_event_loop_group *el_group = aws_event_loop_group_new_default(allocator, 1, NULL); + struct aws_exponential_backoff_retry_options config = { + .max_retries = 3, + .no_retries = true, + .el_group = el_group, + }; + + struct aws_retry_strategy *retry_strategy = aws_retry_strategy_new_exponential_backoff(allocator, &config); + ASSERT_NOT_NULL(retry_strategy); + + struct exponential_backoff_test_data test_data = { + .retry_count = 0, + .failure_error_code = 0, + .mutex = AWS_MUTEX_INIT, + .cvar = AWS_CONDITION_VARIABLE_INIT, + }; + + ASSERT_SUCCESS(aws_mutex_lock(&test_data.mutex)); + ASSERT_ERROR(AWS_IO_RETRY_PERMISSION_DENIED, aws_retry_strategy_acquire_retry_token( + retry_strategy, NULL, s_too_many_retries_test_token_acquired, &test_data, 0)); + + aws_mutex_unlock(&test_data.mutex); + + ASSERT_UINT_EQUALS(0, test_data.retry_count); + + aws_retry_strategy_release(retry_strategy); + aws_event_loop_group_release(el_group); + + aws_io_library_clean_up(); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(test_exponential_backoff_no_retries, s_test_exponential_backoff_no_retries_fn)