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

Build services with a derived configuration object #3095

Merged
merged 10 commits into from
Oct 30, 2023
6 changes: 6 additions & 0 deletions CHANGELOG.next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -498,3 +498,9 @@ message = "`ByteStream::poll_next` is now feature-gated. You can turn on a cargo
references = ["smithy-rs#3033", "smithy-rs#3088"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all" }
author = "ysaito1001"

[[smithy-rs]]
message = "Service builder initialization now takes in a `${serviceName}Config` object on which plugins and layers should be registered. The `builder_with_plugins` and `builder_without_plugins` methods on the service builder, as well as the `layer` method on the built service have been deprecated, and will be removed in a future release. See the [upgrade guidance](https://github.com/awslabs/smithy-rs/discussions/3096) for more details."
references = ["smithy-rs#3095", "smithy-rs#3096"]
meta = { "breaking" = true, "tada" = false, "bug" = true, "target" = "server" }
author = "david-perez"
Original file line number Diff line number Diff line change
Expand Up @@ -551,10 +551,7 @@ class RustWriter private constructor(
if (this.className.contains("AbstractCodeWriter") || this.className.startsWith("java.lang")) {
return false
}
if (this.fileName == "RustWriter.kt") {
return false
}
return true
return this.fileName != "RustWriter.kt"
}

private val preamble = mutableListOf<Writable>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerRootGe
import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerRuntimeTypesReExportsGenerator
import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerServiceGenerator
import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerStructureConstrainedTraitImpl
import software.amazon.smithy.rust.codegen.server.smithy.generators.ServiceConfigGenerator
import software.amazon.smithy.rust.codegen.server.smithy.generators.UnconstrainedCollectionGenerator
import software.amazon.smithy.rust.codegen.server.smithy.generators.UnconstrainedMapGenerator
import software.amazon.smithy.rust.codegen.server.smithy.generators.UnconstrainedUnionGenerator
Expand Down Expand Up @@ -590,29 +591,31 @@ open class ServerCodegenVisitor(
logger.info("[rust-server-codegen] Generating a service $shape")
val serverProtocol = protocolGeneratorFactory.protocol(codegenContext) as ServerProtocol

// Generate root
// Generate root.
rustCrate.lib {
ServerRootGenerator(
serverProtocol,
codegenContext,
).render(this)
}

// Generate server re-exports
// Generate server re-exports.
rustCrate.withModule(ServerRustModule.Server) {
ServerRuntimeTypesReExportsGenerator(codegenContext).render(this)
}

// Generate protocol tests
// Generate protocol tests.
protocolTests()

// Generate service module
// Generate service module.
rustCrate.withModule(ServerRustModule.Service) {
ServerServiceGenerator(
codegenContext,
serverProtocol,
).render(this)

ServiceConfigGenerator(codegenContext).render(this)

ScopeMacroGenerator(codegenContext).render(this)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ open class ServerRootGenerator(
//! ```rust,no_run
//! ## use std::net::SocketAddr;
//! ## async fn dummy() {
//! use $crateName::$serviceName;
//! use $crateName::{${serviceName}Config, $serviceName};
Copy link
Contributor

Choose a reason for hiding this comment

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

nit but shouldn't $serviceName go first?

//!
//! ## let app = $serviceName::builder_without_plugins().build_unchecked();
//! ## let app = $serviceName::builder(${serviceName}Config::builder().build()).build_unchecked();
//! let server = app.into_make_service();
//! let bind: SocketAddr = "127.0.0.1:6969".parse()
//! .expect("unable to parse the server bind address and port");
Expand All @@ -92,36 +92,34 @@ open class ServerRootGenerator(
//! use $crateName::$serviceName;
//!
//! ## async fn dummy() {
//! ## let app = $serviceName::builder_without_plugins().build_unchecked();
//! ## let app = $serviceName::builder(${serviceName}Config::builder().build()).build_unchecked();
//! let handler = LambdaHandler::new(app);
//! lambda_http::run(handler).await.unwrap();
//! ## }
//! ```
//!
//! ## Building the $serviceName
//!
//! To construct [`$serviceName`] we use [`$builderName`] returned by [`$serviceName::builder_without_plugins`]
//! or [`$serviceName::builder_with_plugins`].
//! To construct [`$serviceName`] we use [`$builderName`] returned by [`$serviceName::builder`].
//!
//! #### Plugins
//!
//! The [`$serviceName::builder_with_plugins`] method, returning [`$builderName`],
//! accepts a plugin marked with [`HttpMarker`](aws_smithy_http_server::plugin::HttpMarker) and a
//! plugin marked with [`ModelMarker`](aws_smithy_http_server::plugin::ModelMarker).
//! The [`$serviceName::builder`] method, returning [`$builderName`],
//! accepts a config object on which plugins can be registered.
//! Plugins allow you to build middleware which is aware of the operation it is being applied to.
//!
//! ```rust
//! ## use #{SmithyHttpServer}::plugin::IdentityPlugin;
//! ```rust,no_run
//! ## use #{SmithyHttpServer}::plugin::IdentityPlugin as LoggingPlugin;
//! ## use #{SmithyHttpServer}::plugin::IdentityPlugin as MetricsPlugin;
//! ## use #{Hyper}::Body;
//! use #{SmithyHttpServer}::plugin::HttpPlugins;
//! use $crateName::{$serviceName, $builderName};
//! use $crateName::{${serviceName}Config, $serviceName, $builderName};
//!
//! let http_plugins = HttpPlugins::new()
//! .push(LoggingPlugin)
//! .push(MetricsPlugin);
//! let builder: $builderName<Body, _, _> = $serviceName::builder_with_plugins(http_plugins, IdentityPlugin);
//! let config = ${serviceName}Config::builder().build();
//! let builder: $builderName<Body, _, _, _> = $serviceName::builder(config);
//! ```
//!
//! Check out [`#{SmithyHttpServer}::plugin`] to learn more about plugins.
Expand All @@ -136,7 +134,7 @@ open class ServerRootGenerator(
//! * A `Result<Output, Error>` if your operation has modeled errors, or
//! * An `Output` otherwise.
//!
//! ```rust
//! ```rust,no_run
//! ## struct Input;
//! ## struct Output;
//! ## struct Error;
Expand All @@ -147,7 +145,7 @@ open class ServerRootGenerator(
//!
//! Handlers can accept up to 8 extractors:
//!
//! ```rust
//! ```rust,no_run
//! ## struct Input;
//! ## struct Output;
//! ## struct Error;
Expand Down Expand Up @@ -187,11 +185,12 @@ open class ServerRootGenerator(
//!
//! ```rust
//! ## use std::net::SocketAddr;
//! use $crateName::$serviceName;
//! use $crateName::{${serviceName}Config, $serviceName};
//!
//! ##[#{Tokio}::main]
//! pub async fn main() {
//! let app = $serviceName::builder_without_plugins()
//! let config = ${serviceName}Config::builder().build();
//! let app = $serviceName::builder(config)
${builderFieldNames.values.joinToString("\n") { "//! .$it($it)" }}
//! .build()
//! .expect("failed to build an instance of $serviceName");
Expand Down Expand Up @@ -237,6 +236,6 @@ open class ServerRootGenerator(
fun render(rustWriter: RustWriter) {
documentation(rustWriter)

rustWriter.rust("pub use crate::service::{$serviceName, ${serviceName}Builder, MissingOperationsError};")
rustWriter.rust("pub use crate::service::{$serviceName, ${serviceName}Config, ${serviceName}ConfigBuilder, ${serviceName}Builder, MissingOperationsError};")
}
}
Loading
Loading