Unverified Commit 3fe5efce authored by Zelda Hessler's avatar Zelda Hessler Committed by GitHub
Browse files

update: Ensure service stack is Send + Sync (#851)



* update: ensure RetryHandler is send + sync
update: ensure service stack is send + sync

* Update rust-runtime/aws-smithy-client/src/lib.rs

Co-authored-by: default avatarJohn DiSanti <jdisanti@amazon.com>
parent d215bb08
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -149,6 +149,10 @@ impl<C, M> Client<C, M> {
    }
}

fn check_send_sync<T: Send + Sync>(t: T) -> T {
    t
}

impl<C, M, R> Client<C, M, R>
where
    C: bounds::SmithyConnector,
@@ -161,6 +165,8 @@ where
    /// access the raw response use `call_raw`.
    pub async fn call<O, T, E, Retry>(&self, input: Operation<O, Retry>) -> Result<T, SdkError<E>>
    where
        O: Send + Sync,
        Retry: Send + Sync,
        R::Policy: bounds::SmithyRetryPolicy<O, T, E, Retry>,
        bounds::Parsed<<M as bounds::SmithyMiddleware<C>>::Service, O, Retry>:
            Service<Operation<O, Retry>, Response = SdkSuccess<T>, Error = SdkError<E>> + Clone,
@@ -177,6 +183,8 @@ where
        input: Operation<O, Retry>,
    ) -> Result<SdkSuccess<T>, SdkError<E>>
    where
        O: Send + Sync,
        Retry: Send + Sync,
        R::Policy: bounds::SmithyRetryPolicy<O, T, E, Retry>,
        // This bound is not _technically_ inferred by all the previous bounds, but in practice it
        // is because _we_ know that there is only implementation of Service for Parsed
@@ -188,16 +196,17 @@ where
            Service<Operation<O, Retry>, Response = SdkSuccess<T>, Error = SdkError<E>> + Clone,
    {
        let connector = self.connector.clone();
        let mut svc = ServiceBuilder::new()
        let svc = ServiceBuilder::new()
            // Create a new request-scoped policy
            .retry(self.retry_policy.new_request_policy())
            .layer(ParseResponseLayer::<O, Retry>::new())
            // These layers can be considered as occuring in order. That is, first invoke the
            // These layers can be considered as occurring in order. That is, first invoke the
            // customer-provided middleware, then dispatch dispatch over the wire.
            .layer(&self.middleware)
            .layer(DispatchLayer::new())
            .service(connector);
        svc.ready().await?.call(input).await

        check_send_sync(svc).ready().await?.call(input).await
    }

    /// Statically check the validity of a `Client` without a request to send.
+6 −3
Original line number Diff line number Diff line
@@ -32,7 +32,10 @@ use tracing::Instrument;
/// Implementors are essentially "policy factories" that can produce a new instance of a retry
/// policy mechanism for each request, which allows both shared global state _and_ per-request
/// local state.
pub trait NewRequestPolicy {
pub trait NewRequestPolicy
where
    Self::Policy: Send + Sync,
{
    /// The type of the per-request policy mechanism.
    type Policy;

@@ -292,7 +295,7 @@ where
    Handler: Clone,
    R: ClassifyResponse<SdkSuccess<T>, SdkError<E>>,
{
    type Future = Pin<Box<dyn Future<Output = Self> + Send>>;
    type Future = Pin<Box<dyn Future<Output = Self> + Send + Sync>>;

    fn retry(
        &self,
@@ -321,7 +324,7 @@ where
    }
}

fn check_send_sync<T: Send>(t: T) -> T {
fn check_send_sync<T: Send + Sync>(t: T) -> T {
    t
}