-
Notifications
You must be signed in to change notification settings - Fork 35
feat: Make lots of types Sendable #1009
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 30 commits
ed3ec20
27db4a0
8899fcb
0e7f5d2
d2ec83b
dd02d3b
a8348ad
9f993b5
8cfaac4
3b61b79
2cd0055
6cc642f
f4027b4
f711449
6d202c6
e70bf74
3cb3cb2
08ce751
e00911e
2bba117
dcce994
04e34b0
2561ddd
cbb5b0d
22fce59
c0621bd
de11664
ee88a8c
38842f1
7b6f40e
9b5b796
c6f86b2
ab27b30
a2841f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // | ||
| // Copyright Amazon.com Inc. or its affiliates. | ||
| // All Rights Reserved. | ||
| // | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| // | ||
|
|
||
| import class SmithyHTTPAPI.HTTPRequest | ||
| import class SmithyHTTPAPI.HTTPResponse | ||
|
|
||
| /// A `Sendable` wrapper for `HttpInterceptorProvider` that enables safe concurrent access. | ||
| /// | ||
| /// This wrapper allows non-`Sendable` HTTP interceptor providers to be stored in `Sendable` contexts | ||
| /// by boxing them and forwarding method calls. | ||
| /// | ||
| /// Note: Uses `@unchecked Sendable` because the wrapper is designed to safely encapsulate | ||
| /// non-Sendable providers for use in concurrent contexts. The safety is ensured by the | ||
| /// immutability of the stored provider reference. | ||
| public struct SendableHttpInterceptorProviderBox: HttpInterceptorProvider, @unchecked Sendable { | ||
| internal let _provider: any HttpInterceptorProvider | ||
|
|
||
| public init(_ provider: any HttpInterceptorProvider) { | ||
| self._provider = provider | ||
| } | ||
|
|
||
| public func create<InputType, OutputType>() -> any Interceptor<InputType, OutputType, HTTPRequest, HTTPResponse> { | ||
| return _provider.create() | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| // | ||
| // Copyright Amazon.com Inc. or its affiliates. | ||
| // All Rights Reserved. | ||
| // | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| // | ||
|
|
||
| import protocol Smithy.RequestMessage | ||
| import protocol Smithy.ResponseMessage | ||
|
|
||
| /// A `Sendable` wrapper for `InterceptorProvider` that enables safe concurrent access. | ||
| /// | ||
| /// This wrapper allows non-`Sendable` interceptor providers to be stored in `Sendable` contexts | ||
| /// by boxing them and forwarding method calls. | ||
| /// | ||
| /// Note: Uses `@unchecked Sendable` because the wrapper is designed to safely encapsulate | ||
| /// non-Sendable providers for use in concurrent contexts. The safety is ensured by the | ||
| /// immutability of the stored provider reference. | ||
| public struct SendableInterceptorProviderBox: InterceptorProvider, @unchecked Sendable { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We will be able to remove these wrapper types once we deprecate the class based config. The purpose of these wrappers is to allow the new struct based config to fully support being marked as sendable. |
||
| internal let _provider: any InterceptorProvider | ||
|
|
||
| public init(_ provider: any InterceptorProvider) { | ||
| self._provider = provider | ||
| } | ||
|
|
||
| public func create< | ||
| InputType, | ||
| OutputType, | ||
| RequestType: RequestMessage, | ||
| ResponseType: ResponseMessage | ||
| >() -> any Interceptor<InputType, OutputType, RequestType, ResponseType> { | ||
| return _provider.create() | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,14 +33,22 @@ public struct PaginatorSequence<OperationStackInput: PaginateToken, OperationSta | |
| var token: OperationStackInput.Token? | ||
| var isFirstPage: Bool = true | ||
|
|
||
| // swiftlint:disable force_cast | ||
| public mutating func next() async throws -> OperationStackOutput? { | ||
| while token != nil || isFirstPage { | ||
|
|
||
| if let token = token, | ||
| (token is String && !(token as! String).isEmpty) || | ||
| (token is [String: Any] && !(token as! [String: Any]).isEmpty) { | ||
| self.input = input.usingPaginationToken(token) | ||
| if let token = token { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changed for readability when solving a bug, allows us to remove swiftlint disable |
||
| let shouldUsePaginationToken: Bool | ||
| if let stringToken = token as? String { | ||
| shouldUsePaginationToken = !stringToken.isEmpty | ||
| } else if let dictToken = token as? [String: Any] { | ||
| shouldUsePaginationToken = !dictToken.isEmpty | ||
| } else { | ||
| shouldUsePaginationToken = true | ||
| } | ||
|
|
||
| if shouldUsePaginationToken { | ||
| self.input = input.usingPaginationToken(token) | ||
| } | ||
| } | ||
| let output = try await sequence.paginationFunction(input) | ||
| isFirstPage = false | ||
|
|
@@ -62,7 +70,6 @@ public struct PaginatorSequence<OperationStackInput: PaginateToken, OperationSta | |
| } | ||
| return nil | ||
| } | ||
| // swiftlint:enable force_cast | ||
| } | ||
|
|
||
| public func makeAsyncIterator() -> PaginationIterator { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,14 +21,14 @@ public class AuthSchemePlugin: Plugin { | |
| self.authSchemes = authSchemes | ||
| } | ||
|
|
||
| public func configureClient(clientConfiguration: ClientConfiguration) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per discussion, param should be |
||
| if var config = clientConfiguration as? DefaultHttpClientConfiguration { | ||
| if self.authSchemes != nil { | ||
| config.authSchemes = self.authSchemes! | ||
| } | ||
| if self.authSchemeResolver != nil { | ||
| config.authSchemeResolver = self.authSchemeResolver! | ||
| } | ||
| public func configureClient(clientConfiguration: inout ClientConfiguration) async throws { | ||
| guard var config = clientConfiguration as? any DefaultHttpClientConfiguration else { return } | ||
| if self.authSchemes != nil { | ||
| config.authSchemes = self.authSchemes! | ||
| } | ||
| if self.authSchemeResolver != nil { | ||
| config.authSchemeResolver = self.authSchemeResolver! | ||
| } | ||
| clientConfiguration = config | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as below, see comment on SendableInterceptorProviderBox