diff --git a/include/aws/io/retry_strategy.h b/include/aws/io/retry_strategy.h index 3d63c35e6..ff9d53015 100644 --- a/include/aws/io/retry_strategy.h +++ b/include/aws/io/retry_strategy.h @@ -106,13 +106,13 @@ 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; /** Jitter mode to use, see comments for aws_exponential_backoff_jitter_mode. * Default is AWS_EXPONENTIAL_BACKOFF_JITTER_DEFAULT */ @@ -139,6 +139,14 @@ struct aws_exponential_backoff_retry_options { const struct aws_shutdown_callback_options *shutdown_options; }; +struct aws_no_retry_options { + /** + * Optional shutdown callback that gets invoked, with appropriate user data, + * when the resources used by the retry_strategy are no longer in use. + */ + const struct aws_shutdown_callback_options *shutdown_options; +}; + struct aws_standard_retry_options { struct aws_exponential_backoff_retry_options backoff_retry_options; /** capacity for partitions. Defaults to 500 */ @@ -235,6 +243,16 @@ AWS_IO_API struct aws_retry_strategy *aws_retry_strategy_new_standard( struct aws_allocator *allocator, const struct aws_standard_retry_options *config); +/** + * This retry strategy is used to disable retries. Passed config can be null. + * Calling `aws_retry_strategy_acquire_retry_token` will raise error `AWS_IO_RETRY_PERMISSION_DENIED`. + * Calling any function apart from the `aws_retry_strategy_acquire_retry_token` and `aws_retry_strategy_release` will + * result in a fatal error. + */ +AWS_IO_API struct aws_retry_strategy *aws_retry_strategy_new_no_retry( + struct aws_allocator *allocator, + const struct aws_no_retry_options *config); + AWS_EXTERN_C_END AWS_POP_SANE_WARNING_LEVEL diff --git a/source/no_retry_strategy.c b/source/no_retry_strategy.c new file mode 100644 index 000000000..389d2de1f --- /dev/null +++ b/source/no_retry_strategy.c @@ -0,0 +1,85 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include +#include +#include + +struct aws_retry_strategy_no_retries { + struct aws_retry_strategy base; + struct aws_shutdown_callback_options shutdown_options; +}; + +static void s_no_retry_destroy(struct aws_retry_strategy *retry_strategy) { + if (retry_strategy) { + struct aws_retry_strategy_no_retries *strategy = retry_strategy->impl; + aws_simple_completion_callback *completion_callback = strategy->shutdown_options.shutdown_callback_fn; + void *completion_user_data = strategy->shutdown_options.shutdown_callback_user_data; + + aws_mem_release(retry_strategy->allocator, strategy); + if (completion_callback != NULL) { + completion_callback(completion_user_data); + } + } +} + +static int s_no_retry_acquire_token( + struct aws_retry_strategy *retry_strategy, + const struct aws_byte_cursor *partition_id, + aws_retry_strategy_on_retry_token_acquired_fn *on_acquired, + void *user_data, + uint64_t timeout_ms) { + (void)retry_strategy; + (void)partition_id; + (void)on_acquired; + (void)user_data; + (void)timeout_ms; + return aws_raise_error(AWS_IO_RETRY_PERMISSION_DENIED); +} + +static int s_no_retry_schedule_retry( + struct aws_retry_token *token, + enum aws_retry_error_type error_type, + aws_retry_strategy_on_retry_ready_fn *retry_ready, + void *user_data) { + (void)token; + (void)error_type; + (void)retry_ready; + (void)user_data; + AWS_FATAL_ASSERT(0 && "schedule_retry must not be called for no_retries retry strategy"); +} + +static int s_no_retry_record_success(struct aws_retry_token *token) { + (void)token; + AWS_FATAL_ASSERT(0 && "record_success must not be called for no_retries retry strategy"); +} + +static void s_no_retry_release_token(struct aws_retry_token *token) { + (void)token; + AWS_FATAL_ASSERT(0 && "release_token must not be called for no_retries retry strategy"); +} + +static struct aws_retry_strategy_vtable s_exponential_retry_vtable = { + .destroy = s_no_retry_destroy, + .acquire_token = s_no_retry_acquire_token, + .schedule_retry = s_no_retry_schedule_retry, + .record_success = s_no_retry_record_success, + .release_token = s_no_retry_release_token, +}; + +struct aws_retry_strategy *aws_retry_strategy_new_no_retry( + struct aws_allocator *allocator, + const struct aws_no_retry_options *config) { + struct aws_retry_strategy_no_retries *strategy = + aws_mem_calloc(allocator, 1, sizeof(struct aws_retry_strategy_no_retries)); + strategy->base.allocator = allocator; + strategy->base.impl = strategy; + strategy->base.vtable = &s_exponential_retry_vtable; + aws_atomic_init_int(&strategy->base.ref_count, 1); + + if (config != NULL && config->shutdown_options) { + strategy->shutdown_options = *config->shutdown_options; + } + return &strategy->base; +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fbcd3088c..dc4c07b41 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_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/no_retry_strategy_test.c b/tests/no_retry_strategy_test.c new file mode 100644 index 000000000..5cd04f868 --- /dev/null +++ b/tests/no_retry_strategy_test.c @@ -0,0 +1,27 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include +#include +#include + +static int s_test_no_retries_fn(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + + aws_io_library_init(allocator); + + struct aws_retry_strategy *retry_strategy = aws_retry_strategy_new_no_retry(allocator, NULL); + ASSERT_NOT_NULL(retry_strategy); + + ASSERT_ERROR( + AWS_IO_RETRY_PERMISSION_DENIED, aws_retry_strategy_acquire_retry_token(retry_strategy, NULL, NULL, NULL, 0)); + + aws_retry_strategy_release(retry_strategy); + + aws_io_library_clean_up(); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(test_no_retries, s_test_no_retries_fn)