diff options
| author | Bilal Acar <88554275+biacar@users.noreply.github.com> | 2021-08-13 09:41:17 -0700 |
|---|---|---|
| committer | Michael Klishin <michael@clojurewerkz.org> | 2021-08-21 00:45:07 +0300 |
| commit | 50f9bcf504c6c6fc2bad0108f0d79e741010a066 (patch) | |
| tree | 0839c04744c0a42f8f1c52cf2f1f9f9b61181f30 | |
| parent | 11760f95bdf6322dd7b300be8701bf6235e4d8ae (diff) | |
| download | rabbitmq-server-git-50f9bcf504c6c6fc2bad0108f0d79e741010a066.tar.gz | |
Adding retries to AWS API calls
Adding retries to AWS API calls
| -rw-r--r-- | deps/rabbitmq_aws/include/rabbitmq_aws.hrl | 3 | ||||
| -rw-r--r-- | deps/rabbitmq_aws/src/rabbitmq_aws.erl | 14 | ||||
| -rw-r--r-- | deps/rabbitmq_aws/test/src/rabbitmq_aws_tests.erl | 20 |
3 files changed, 34 insertions, 3 deletions
diff --git a/deps/rabbitmq_aws/include/rabbitmq_aws.hrl b/deps/rabbitmq_aws/include/rabbitmq_aws.hrl index 36e40cbd0a..6b104c10bc 100644 --- a/deps/rabbitmq_aws/include/rabbitmq_aws.hrl +++ b/deps/rabbitmq_aws/include/rabbitmq_aws.hrl @@ -43,6 +43,9 @@ -define(METADATA_TOKEN, "X-aws-ec2-metadata-token"). +-define(LINEAR_BACK_OFF_MILLIS, 500). +-define(MAX_RETRIES, 5). + -type access_key() :: nonempty_string(). -type secret_access_key() :: nonempty_string(). -type expiration() :: calendar:datetime() | undefined. diff --git a/deps/rabbitmq_aws/src/rabbitmq_aws.erl b/deps/rabbitmq_aws/src/rabbitmq_aws.erl index 5ba4e61b50..3ba6e58b12 100644 --- a/deps/rabbitmq_aws/src/rabbitmq_aws.erl +++ b/deps/rabbitmq_aws/src/rabbitmq_aws.erl @@ -543,10 +543,22 @@ ensure_credentials_valid() -> %% @end api_get_request(Service, Path) -> rabbit_log:debug("Invoking AWS request {Service: ~p; Path: ~p}...", [Service, Path]), + api_get_request_with_retries(Service, Path, ?MAX_RETRIES, ?LINEAR_BACK_OFF_MILLIS). + + + -spec api_get_request_with_retries(string(), path(), integer(), integer()) -> result(). + %% @doc Invoke an API call to an AWS service with retries. + %% @end +api_get_request_with_retries(Service, Path, Retries, WaitTimeBetweenRetries) -> ensure_credentials_valid(), case get(Service, Path) of {ok, {_Headers, Payload}} -> rabbit_log:debug("AWS request: ~s~nResponse: ~p", [Path, Payload]), {ok, Payload}; {error, {credentials, _}} -> {error, credentials}; - {error, Message, _} -> {error, Message} + {error, Message, _} -> case Retries of + 0 -> {error, Message}; + _ -> rabbit_log:warning("Error occurred ~s~nWill retry AWS request, remaining retries: ~b", [Message, Retries]), + timer:sleep(WaitTimeBetweenRetries), + api_get_request_with_retries(Service, Path, Retries - 1, WaitTimeBetweenRetries) + end end. diff --git a/deps/rabbitmq_aws/test/src/rabbitmq_aws_tests.erl b/deps/rabbitmq_aws/test/src/rabbitmq_aws_tests.erl index b73b091e5b..1882447942 100644 --- a/deps/rabbitmq_aws/test/src/rabbitmq_aws_tests.erl +++ b/deps/rabbitmq_aws/test/src/rabbitmq_aws_tests.erl @@ -479,7 +479,7 @@ api_get_request_test_() -> ?assertEqual({error, credentials}, Result) end }, - {"AWS service API request failed - API error", + {"AWS service API request failed - API error with persistent failure", fun() -> State = #state{access_key = "ExpiredKey", secret_access_key = "ExpiredAccessKey", @@ -489,11 +489,27 @@ api_get_request_test_() -> {ok, Pid} = rabbitmq_aws:start_link(), rabbitmq_aws:set_region("us-east-1"), rabbitmq_aws:set_credentials(State), - Result = rabbitmq_aws:api_get_request("AWS", "API"), + Result = rabbitmq_aws:api_get_request_with_retries("AWS", "API", 3, 1), ok = gen_server:stop(Pid), ?assertEqual({error, "invalid input"}, Result), meck:validate(httpc) end + }, + {"AWS service API request succeeded after a transient error", + fun() -> + State = #state{access_key = "ExpiredKey", + secret_access_key = "ExpiredAccessKey", + region = "us-east-1", + expiration = {{3016, 4, 1}, {12, 0, 0}}}, + meck:expect(httpc, request, 4, meck:seq([{error, "invalid input"}, {ok, {{"HTTP/1.0", 200, "OK"}, [{"content-type", "application/json"}], "{\"data\": \"value\"}"}}])), + {ok, Pid} = rabbitmq_aws:start_link(), + rabbitmq_aws:set_region("us-east-1"), + rabbitmq_aws:set_credentials(State), + Result = rabbitmq_aws:api_get_request_with_retries("AWS", "API", 3, 1), + ok = gen_server:stop(Pid), + ?assertEqual({ok, [{"data","value"}]}, Result), + meck:validate(httpc) + end } ] }. |
