smelter_aws_fargate/
client.rs1use std::marker::PhantomData;
3
4use aws_sdk_ecs::{
5 config::retry::ClassifyRetry,
6 error::ProvideErrorMetadata,
7 operation::{
8 describe_tasks::DescribeTasksError, run_task::RunTaskError, stop_task::StopTaskError,
9 },
10};
11use aws_sdk_s3::config::{interceptors::InterceptorContext, retry::RetryAction};
12use aws_smithy_runtime_api::client::retries::classifiers::SharedRetryClassifier;
13
14pub fn build_ecs_client_config(sdk_config: &aws_config::SdkConfig) -> aws_sdk_ecs::config::Builder {
17 let mut builder = aws_sdk_ecs::config::Builder::from(sdk_config);
18
19 let retry_config = aws_sdk_ecs::config::retry::RetryConfig::adaptive()
20 .with_initial_backoff(std::time::Duration::from_secs(2))
21 .with_max_attempts(5)
22 .with_max_backoff(std::time::Duration::from_secs(20));
23
24 builder.set_retry_config(Some(retry_config));
25
26 builder.push_retry_classifier(SharedRetryClassifier::new(RateLimitErrorClassifier::<
29 DescribeTasksError,
30 >::new()));
31 builder.push_retry_classifier(SharedRetryClassifier::new(RateLimitErrorClassifier::<
32 RunTaskError,
33 >::new()));
34 builder.push_retry_classifier(SharedRetryClassifier::new(RateLimitErrorClassifier::<
35 StopTaskError,
36 >::new()));
37
38 builder
39}
40
41#[derive(Debug, Default)]
44pub struct RateLimitErrorClassifier<E> {
45 _marker: PhantomData<E>,
46}
47
48impl<E> RateLimitErrorClassifier<E> {
49 pub fn new() -> Self {
51 Self {
52 _marker: PhantomData,
53 }
54 }
55}
56
57impl<E> ClassifyRetry for RateLimitErrorClassifier<E>
58where
59 E: std::error::Error + ProvideErrorMetadata + Send + Sync + 'static,
61{
62 fn classify_retry(&self, ctx: &InterceptorContext) -> RetryAction {
63 let output_or_error = ctx.output_or_error();
65 let error = match output_or_error {
67 Some(Ok(_)) | None => return RetryAction::NoActionIndicated,
68 Some(Err(err)) => err,
69 };
70
71 let rate_throttle_error = error
73 .as_operation_error()
74 .and_then(|err| err.downcast_ref::<aws_sdk_ecs::error::SdkError<E>>())
75 .and_then(|err| err.as_service_error())
76 .and_then(|err| err.code())
77 .map(|code| code == "ThrottlingException")
78 .unwrap_or(false);
79
80 if rate_throttle_error {
81 RetryAction::throttling_error()
83 } else {
84 RetryAction::NoActionIndicated
87 }
88 }
89
90 fn name(&self) -> &'static str {
91 "ThrottlingException Classifier"
92 }
93}