-
Notifications
You must be signed in to change notification settings - Fork 187
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
Orchestrator ResponseDeserializer
codegen and auth
#2494
Conversation
Co-authored-by: John DiSanti <[email protected]>
Co-authored-by: John DiSanti <[email protected]>
update: retry handling in orchestrator
A new generated diff is ready to view.
A new doc preview is ready to view. |
ResponseDeserializer
trait impls for the orchestratorResponseDeserializer
codegen and auth
A new generated diff is ready to view.
A new doc preview is ready to view. |
use std::ops::{Deref, DerefMut}; | ||
|
||
#[derive(Debug)] | ||
pub struct TypedBox<T> { |
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.
I would love to see docs for this. Why does this exist? What does it allow us to do that we couldn't otherwise?
@@ -58,6 +58,12 @@ impl<B> RequestId for http::Response<B> { | |||
} | |||
} | |||
|
|||
impl RequestId for HeaderMap { | |||
fn request_id(&self) -> Option<&str> { | |||
extract_request_id(self) |
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.
When should functions that return an option have a try
prefix? I'd ask the same question for traits too. Do we expect to only ever have a fallible version of this trait? I can see that being the case but I wanted to confirm.
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.
This one will definitely always be fallible.
fn extended_request_id(&self) -> Option<&str> { | ||
extract_extended_request_id(self) | ||
} |
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.
What is an "extended" request ID? I'm not familiar with that phrasing.
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.
Oh, this must be referring to that S3-specific way of sending it, right?
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.
Yeah, this is the S3 extended request ID.
// TODO(enableNewSmithyRuntime): Implement checksumming via interceptor and delete this decorator | ||
private fun applies(codegenContext: ClientCodegenContext): Boolean = | ||
!codegenContext.settings.codegenConfig.enableNewSmithyRuntime | ||
|
||
override fun operationCustomizations( | ||
codegenContext: ClientCodegenContext, | ||
operation: OperationShape, | ||
baseCustomizations: List<OperationCustomization>, | ||
): List<OperationCustomization> { | ||
return baseCustomizations + HttpRequestChecksumCustomization(codegenContext, operation) | ||
): List<OperationCustomization> = baseCustomizations.letIf(applies(codegenContext)) { | ||
it + HttpRequestChecksumCustomization(codegenContext, operation) | ||
} | ||
} |
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.
This adds code to make_operation
but I'd assumed we'd no longer be generating/calling that. Are we using it somehow? If not, why generate the code for it?
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.
I'm currently continuing to generate make_operation
for now to keep things compiling. I haven't made enough codegen progress to stop generating some pieces.
aws/sra-test/build.gradle.kts
Outdated
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.
Thanks for setting this up.
private val orchestratorCodegenScope by lazy { | ||
arrayOf( | ||
"Error" to CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("client::interceptors::context::Error"), | ||
"HttpResponse" to CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("client::orchestrator::HttpResponse"), | ||
"Instrument" to CargoDependency.Tracing.toType().resolve("Instrument"), | ||
"Output" to CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("client::interceptors::context::Output"), | ||
"OutputOrError" to CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("client::interceptors::context::OutputOrError"), | ||
"ResponseDeserializer" to CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("client::orchestrator::ResponseDeserializer"), | ||
"SdkBody" to RuntimeType.sdkBody(runtimeConfig), | ||
"SdkError" to RuntimeType.sdkError(runtimeConfig), | ||
"TypedBox" to CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("type_erasure::TypedBox"), | ||
"debug_span" to RuntimeType.Tracing.resolve("debug_span"), | ||
"type_erase_result" to typeEraseResult(), | ||
) | ||
} |
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.
This is a teeny bit more readable with some aliasing.
private val orchestratorCodegenScope by lazy { | |
arrayOf( | |
"Error" to CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("client::interceptors::context::Error"), | |
"HttpResponse" to CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("client::orchestrator::HttpResponse"), | |
"Instrument" to CargoDependency.Tracing.toType().resolve("Instrument"), | |
"Output" to CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("client::interceptors::context::Output"), | |
"OutputOrError" to CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("client::interceptors::context::OutputOrError"), | |
"ResponseDeserializer" to CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("client::orchestrator::ResponseDeserializer"), | |
"SdkBody" to RuntimeType.sdkBody(runtimeConfig), | |
"SdkError" to RuntimeType.sdkError(runtimeConfig), | |
"TypedBox" to CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("type_erasure::TypedBox"), | |
"debug_span" to RuntimeType.Tracing.resolve("debug_span"), | |
"type_erase_result" to typeEraseResult(), | |
) | |
} | |
val InterceptorContext = CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("client::interceptors::context"); | |
val Orchestrator = CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("client::orchestrator"); | |
private val orchestratorCodegenScope by lazy { | |
arrayOf( | |
"Error" to InterceptorContext.resolve("Error"), | |
"HttpResponse" to Orchestrator.resolve("HttpResponse"), | |
"Instrument" to CargoDependency.Tracing.toType().resolve("Instrument"), | |
"Output" to InterceptorContext.resolve("Output"), | |
"OutputOrError" to InterceptorContext.resolve("OutputOrError"), | |
"ResponseDeserializer" to Orchestrator.resolve("ResponseDeserializer"), | |
"SdkBody" to RuntimeType.sdkBody(runtimeConfig), | |
"SdkError" to RuntimeType.sdkError(runtimeConfig), | |
"TypedBox" to CargoDependency.smithyRuntimeApi(runtimeConfig).toType().resolve("type_erasure::TypedBox"), | |
"debug_span" to RuntimeType.Tracing.resolve("debug_span"), | |
"type_erase_result" to typeEraseResult(), | |
) | |
} |
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.
These aliases could even be added to RuntimeType.kt
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.
I was a little hesitant to add any conveniences to RuntimeType
to avoid accidental inclusion in the old codegen paths.
private fun typeEraseResult(): RuntimeType = ProtocolFunctions.crossOperationFn("type_erase_result") { fnName -> | ||
rustTemplate( | ||
""" | ||
pub(crate) fn $fnName<O, E>(result: Result<O, E>) -> Result<#{Output}, #{Error}> | ||
where | ||
O: Send + Sync + 'static, | ||
E: Send + Sync + 'static, | ||
{ | ||
result.map(|output| #{TypedBox}::new(output).erase()) | ||
.map_err(|error| #{TypedBox}::new(error).erase()) | ||
} | ||
""", | ||
*orchestratorCodegenScope, | ||
) | ||
} |
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.
I think adding docs or some sort of breadcrumb for people that don't understand why we do type erasure would be helpful
@@ -256,6 +403,43 @@ class HttpBoundProtocolTraitImplGenerator( | |||
val outputSymbol = symbolProvider.toSymbol(outputShape) | |||
val errorSymbol = symbolProvider.symbolForOperationError(operationShape) | |||
return protocolFunctions.deserializeFn(operationShape, fnNameSuffix = "http_response") { fnName -> | |||
Attribute.AllowClippyUnnecessaryWraps.render(this) | |||
rustBlockTemplate( | |||
"pub fn $fnName(response: &mut #{http}::Response<#{SdkBody}>) -> std::result::Result<#{O}, #{E}>", |
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.
We should probably add #[doc(hidden)]
for this
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.
They're in a pub(crate)
module.
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.
I think we should document what the meaning/usage of all the sources are and why you'd choose one over the other. That, or we should create a TODO for that.
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.
Ended up removing the modeled/unmodeled source changes to ServiceError
since they're no longer needed.
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.
This file is long enough that we should consider splitting it.
pub mod client; | ||
|
||
/// A typemap for storing configuration. | ||
pub mod config_bag; | ||
/// Smithy interceptors for smithy clients. | ||
/// | ||
/// Interceptors are lifecycle hooks that can read/modify requests and responses. | ||
pub mod interceptors; | ||
/// Smithy code related to retry handling and token bucket. | ||
/// | ||
/// This code defines when and how failed requests should be retried. It also defines the behavior | ||
/// used to limit the rate that requests are sent. | ||
pub mod retries; | ||
/// Runtime plugin type definitions. | ||
pub mod runtime_plugin; | ||
|
||
pub mod type_erasure; |
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.
Please add docs for these modules here, or in the module files
A new generated diff is ready to view.
A new doc preview is ready to view. |
A new generated diff is ready to view.
A new doc preview is ready to view. |
* Convert interceptor fns to macro invocations Co-authored-by: John DiSanti <[email protected]> * Add unmodeled error to ServiceError and bring in EventLog Co-authored-by: John DiSanti <[email protected]> * Simplify and test `EventLog` * Attempt to integrate the event log with the orchestrator * fix: error type in integration test update: retry handling in orchestrator * update: set the runtime plugins to do nothing instead of panic when called on * Introduce a construct for type erasure * Eliminate several generics and add phased error handling * Code generate the `ResponseDeserializer` trait impls * CI fixes * Reorganize the new runtime crates * Create the `Identity` type * Reorganize orchestrator traits and accessors * Set up code generated test environment for the new runtime * Add initial auth orchestration implementation * Fix clippy lint * Incorporate feedback * Fix external types lint --------- Co-authored-by: Zelda Hessler <[email protected]>
* Convert interceptor fns to macro invocations Co-authored-by: John DiSanti <[email protected]> * Add unmodeled error to ServiceError and bring in EventLog Co-authored-by: John DiSanti <[email protected]> * Simplify and test `EventLog` * Attempt to integrate the event log with the orchestrator * fix: error type in integration test update: retry handling in orchestrator * update: set the runtime plugins to do nothing instead of panic when called on * Introduce a construct for type erasure * Eliminate several generics and add phased error handling * Code generate the `ResponseDeserializer` trait impls * CI fixes * Reorganize the new runtime crates * Create the `Identity` type * Reorganize orchestrator traits and accessors * Set up code generated test environment for the new runtime * Add initial auth orchestration implementation * Fix clippy lint * Incorporate feedback * Fix external types lint --------- Co-authored-by: Zelda Hessler <[email protected]>
Motivation and Context
This PR refactors the orchestrator's error handling and revises the code generator to implement the new
ResponseDeserializer
trait behind theenableNewSmithyRuntime
codegen flag.By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.