use std::time::{Duration, Instant};
use crate::{SdkError, SdkResult};
#[derive(Clone, Debug, Default)]
pub struct WaitForStepCompletionOptions {
pub(crate) request_id: String,
pub(crate) request_timeout: Duration,
pub(crate) internal_handler_timeout: Duration,
}
impl WaitForStepCompletionOptions {
pub fn new() -> Self {
Self::default()
}
pub fn request_id(mut self, request_id: impl Into<String>) -> Self {
self.request_id = request_id.into();
self
}
pub fn request_timeout(mut self, request_timeout: Duration) -> Self {
self.request_timeout = request_timeout;
self
}
pub fn internal_handler_timeout(mut self, internal_handler_timeout: Duration) -> Self {
self.internal_handler_timeout = internal_handler_timeout;
self
}
}
#[derive(Clone, Debug, Default)]
pub struct WaitForAttributeOptions {
pub(crate) request_id: String,
pub(crate) request_timeout: Duration,
pub(crate) internal_handler_timeout: Duration,
}
impl WaitForAttributeOptions {
pub fn new() -> Self {
Self::default()
}
pub fn request_id(mut self, request_id: impl Into<String>) -> Self {
self.request_id = request_id.into();
self
}
pub fn request_timeout(mut self, request_timeout: Duration) -> Self {
self.request_timeout = request_timeout;
self
}
pub fn internal_handler_timeout(mut self, internal_handler_timeout: Duration) -> Self {
self.internal_handler_timeout = internal_handler_timeout;
self
}
}
pub(crate) struct ClientRequestAttempt {
pub(crate) request_timeout_seconds: i32,
pub(crate) transport_timeout: Option<Duration>,
}
pub(crate) struct ClientRequestBudget {
deadline: Option<Instant>,
}
impl ClientRequestBudget {
pub(crate) fn new(request_timeout: Duration) -> SdkResult<Self> {
crate::client::seconds32(request_timeout)?;
Ok(Self {
deadline: (!request_timeout.is_zero()).then(|| Instant::now() + request_timeout),
})
}
pub(crate) fn next_attempt(
&self,
operation: &'static str,
flow_id: &str,
) -> SdkResult<ClientRequestAttempt> {
let Some(deadline) = self.deadline else {
return Ok(ClientRequestAttempt {
request_timeout_seconds: 0,
transport_timeout: None,
});
};
let remaining = deadline.saturating_duration_since(Instant::now());
if remaining.is_zero() {
return Err(SdkError::request_timeout(operation, flow_id));
}
let seconds = remaining.as_secs() + u64::from(remaining.subsec_nanos() > 0);
Ok(ClientRequestAttempt {
request_timeout_seconds: i32::try_from(seconds)
.map_err(|_| crate::client::invalid("Duration exceeds int32"))?,
transport_timeout: Some(remaining),
})
}
pub(crate) fn has_deadline(&self) -> bool {
self.deadline.is_some()
}
}