Skip to content
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

Add boxed method to service builder #1840

Merged
merged 5 commits into from
Oct 25, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ class ServerServiceGeneratorV2(
rustTemplate(
"""
##[derive(Clone)]
pub struct $serviceName<S> {
pub struct $serviceName<S = #{SmithyHttpServer}::routing::Route> {
router: #{SmithyHttpServer}::routers::RoutingService<#{Router}<S>, #{Protocol}>,
}

Expand Down Expand Up @@ -321,6 +321,21 @@ class ServerServiceGeneratorV2(
router: self.router.map(|s| s.layer(layer))
}
}

/// Applies [`Route::new`](#{SmithyHttpServer}::routing::Route::new) to all routes.
///
/// This has the effect of erasing all types accumulated via [`layer`].
pub fn boxed<B>(self) -> $serviceName<#{SmithyHttpServer}::routing::Route<B>>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't this method go in an extension trait in a runtime crate?
Bringing this up because I feel that less generated code is usually better.

Copy link
Contributor

@crisidev crisidev Oct 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually believe the opposite.. generated code is easier to manage and release than runtime code.. the more we codegenerate, the easier is for customers to consume as it is not tied to crates releases.

Copy link
Contributor Author

@hlbarber hlbarber Oct 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this was a standalone function I think it might fit better in the rust-runtime crates but given that this is a small method on a generated struct I think it makes sense to leave it here for now. If we did this via extension trait the customer would have to import the trait to use the method which may be confusing.

It is possible though: we'd need to add a base trait with the layer method on it, impl that onto PokemonService via codegen, and then include this boxed method extension to that trait.

Maybe we should draft out a heuristic to help in this kind of decision making?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we should figure out guidelines to decide whether to put stuff in runtime vs codegen!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case I'd lean towards putting this method in the code generated struct. It's a better developer experience than having to import a single-use extension trait just to call it.

where
S: #{Tower}::Service<
#{Http}::Request<B>,
Response = #{Http}::Response<#{SmithyHttpServer}::body::BoxBody>,
Error = std::convert::Infallible>,
S: Clone + Send + 'static,
S::Future: Send + 'static,
{
self.layer(&#{Tower}::layer::layer_fn(#{SmithyHttpServer}::routing::Route::new))
}
}

impl<B, RespB, S> #{Tower}::Service<#{Http}::Request<B>> for $serviceName<S>
Expand Down