Skip to content

Commit

Permalink
Add "Anatomy of a Service" documentation (#1782)
Browse files Browse the repository at this point in the history
* Rust documentation improvements

* Add "Anatomy of a Service" documentation
  • Loading branch information
hlbarber authored Oct 11, 2022
1 parent 94a991c commit bf3fbc2
Show file tree
Hide file tree
Showing 8 changed files with 922 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class ServerServiceGeneratorV2(
"""
/// Sets the [`$structName`](crate::operation_shape::$structName) operation.
///
/// This should be a closure satisfying the [`Handler`](#{SmithyHttpServer}::operation::Handler) trait.
/// This should be an async function satisfying the [`Handler`](#{SmithyHttpServer}::operation::Handler) trait.
/// See the [operation module documentation](#{SmithyHttpServer}::operation) for more information.
pub fn $fieldName<H, NewExts>(self, value: H) -> $builderName<#{HandlerSetterGenerics:W}>
where
Expand Down Expand Up @@ -312,7 +312,7 @@ class ServerServiceGeneratorV2(
#{SmithyHttpServer}::routing::IntoMakeService::new(self)
}
/// Applies a layer uniformly to all routes.
/// Applies a [`Layer`](#{Tower}::Layer) uniformly to all routes.
pub fn layer<L>(self, layer: &L) -> $serviceName<L::Service>
where
L: #{Tower}::Layer<S>
Expand Down
1 change: 1 addition & 0 deletions design/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- [Generating Common Service Code](./server/code_generation.md)
- [Generating the Pokémon Service](./server/pokemon_service.md)
- [Instrumentation](./server/instrumentation.md)
<!-- - [The Anatomy of a Service](./server/anatomy.md) -->

- [RFCs](./rfcs/overview.md)
- [RFC-0001: Sharing configuration between multiple clients](./rfcs/rfc0001_shared_config.md)
Expand Down
880 changes: 880 additions & 0 deletions design/src/server/anatomy.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions design/src/server/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ Smithy Rust provides the ability to generate a server whose operations are provi
- [Generating Common Service Code](./code_generation.md)
- [Generating the Pokémon Service](./pokemon_service.md)
- [Instrumentation](./instrumentation.md)
<!-- - [The Anatomy of a Service](./anatomy.md) -->
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
* SPDX-License-Identifier: Apache-2.0
*/

use aws_smithy_http_server::plugin::Plugin;
use aws_smithy_http_server::{
operation::{Operation, OperationShape},
plugin::{Pluggable, Plugin},
};
use tower::{layer::util::Stack, Layer, Service};

use std::task::{Context, Poll};

/// A [`Service`](tower::Service) that adds a print log.
#[derive(Clone, Debug)]
Expand All @@ -12,15 +18,15 @@ pub struct PrintService<S> {
name: &'static str,
}

impl<R, S> tower::Service<R> for PrintService<S>
impl<R, S> Service<R> for PrintService<S>
where
S: tower::Service<R>,
S: Service<R>,
{
type Response = S::Response;
type Error = S::Error;
type Future = S::Future;

fn poll_ready(&mut self, cx: &mut std::task::Context<'_>) -> std::task::Poll<Result<(), Self::Error>> {
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}

Expand All @@ -35,7 +41,7 @@ where
pub struct PrintLayer {
name: &'static str,
}
impl<S> tower::Layer<S> for PrintLayer {
impl<S> Layer<S> for PrintLayer {
type Service = PrintService<S>;

fn layer(&self, service: S) -> Self::Service {
Expand All @@ -46,26 +52,24 @@ impl<S> tower::Layer<S> for PrintLayer {
}
}

/// A [`Plugin`]() for a service builder to add a [`PrintLayer`] over operations.
/// A [`Plugin`] for a service builder to add a [`PrintLayer`] over operations.
#[derive(Debug)]
pub struct PrintPlugin;

impl<P, Op, S, L> Plugin<P, Op, S, L> for PrintPlugin
where
Op: aws_smithy_http_server::operation::OperationShape,
Op: OperationShape,
{
type Service = S;
type Layer = tower::layer::util::Stack<L, PrintLayer>;
type Layer = Stack<L, PrintLayer>;

fn map(
&self,
input: aws_smithy_http_server::operation::Operation<S, L>,
) -> aws_smithy_http_server::operation::Operation<Self::Service, Self::Layer> {
fn map(&self, input: Operation<S, L>) -> Operation<Self::Service, Self::Layer> {
input.layer(PrintLayer { name: Op::NAME })
}
}

/// An extension to service builders to add the `print()` function.
pub trait PrintExt: aws_smithy_http_server::plugin::Pluggable<PrintPlugin> {
pub trait PrintExt: Pluggable<PrintPlugin> {
/// Causes all operations to print the operation name when called.
///
/// This works by applying the [`PrintPlugin`].
Expand All @@ -77,4 +81,4 @@ pub trait PrintExt: aws_smithy_http_server::plugin::Pluggable<PrintPlugin> {
}
}

impl<Builder> PrintExt for Builder where Builder: aws_smithy_http_server::plugin::Pluggable<PrintPlugin> {}
impl<Builder> PrintExt for Builder where Builder: Pluggable<PrintPlugin> {}
4 changes: 2 additions & 2 deletions rust-runtime/aws-smithy-http-server/src/operation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
//!
//! ## [`Handler`]
//!
//! The [`Handler`] trait is implemented by all closures which accept [`OperationShape::Input`] as their first
//! The [`Handler`] trait is implemented by all async functions which accept [`OperationShape::Input`] as their first
//! argument, the remaining arguments implement [`FromParts`](crate::request::FromParts), and return either
//! [`OperationShape::Output`] when [`OperationShape::Error`] is [`Infallible`](std::convert::Infallible) or
//! [`Result`]<[`OperationShape::Output`],[`OperationShape::Error`]>. The following are examples of closures which
Expand Down Expand Up @@ -191,7 +191,7 @@ pub use upgrade::*;

/// A Smithy operation, represented by a [`Service`](tower::Service) `S` and a [`Layer`](tower::Layer) `L`.
///
/// The `L` is held and applied lazily during [`Operation::upgrade`].
/// The `L` is held and applied lazily during [`Upgradable::upgrade`].
pub struct Operation<S, L = Identity> {
inner: S,
layer: L,
Expand Down
25 changes: 16 additions & 9 deletions rust-runtime/aws-smithy-http-server/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

use crate::operation::Operation;

/// Provides a standard interface for applying [`Plugin`]s to a service builder. This is implemented automatically for all builders.
/// As [`Plugin`]s modify the way in which [`Operation`]s are [`upgraded`](crate::operation::Upgradable) we can use [`Pluggable`] as a foundation
/// to write extension traits for all builders.
/// Provides a standard interface for applying [`Plugin`]s to a service builder. This is implemented automatically for
/// all builders.
///
/// As [`Plugin`]s modify the way in which [`Operation`]s are [`upgraded`](crate::operation::Upgradable) we can use
/// [`Pluggable`] as a foundation to write extension traits which are implemented for all service builders.
///
/// # Example
///
Expand All @@ -19,29 +21,34 @@ use crate::operation::Operation;
/// self.apply(PrintPlugin)
/// }
/// }
///
/// impl<Builder> PrintExt for Builder where Builder: Pluggable<PrintPlugin> {}
/// ```
pub trait Pluggable<NewPlugin> {
type Output;

/// A service builder applies this `plugin`.
/// Applies a [`Plugin`] to the service builder.
fn apply(self, plugin: NewPlugin) -> Self::Output;
}

/// Maps one [`Operation`] to another,
/// parameterised by the protocol `P` and operation shape `Op` to allow for plugin behaviour to be specialised accordingly.
/// A mapping from one [`Operation`] to another. Used to modify the behavior of
/// [`Upgradable`](crate::operation::Upgradable) and therefore the resulting service builder,
///
/// This is passed to [`Pluggable::apply`] to modify the behaviour of the builder.
pub trait Plugin<P, Op, S, L> {
/// The generics `Protocol` and `Op` allow the behavior to be parameterized.
///
/// Every service builder enjoys [`Pluggable`] and therefore can be provided with a [`Plugin`] using
/// [`Pluggable::apply`].
pub trait Plugin<Protocol, Op, S, L> {
type Service;
type Layer;

/// Map an [`Operation`] to another.
/// Maps an [`Operation`] to another.
fn map(&self, input: Operation<S, L>) -> Operation<Self::Service, Self::Layer>;
}

/// An [`Plugin`] that maps an `input` [`Operation`] to itself.
pub struct IdentityPlugin;

impl<P, Op, S, L> Plugin<P, Op, S, L> for IdentityPlugin {
type Service = S;
type Layer = L;
Expand Down
4 changes: 2 additions & 2 deletions rust-runtime/aws-smithy-http-server/src/routers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ pub trait Router<B> {
fn match_route(&self, request: &http::Request<B>) -> Result<Self::Service, Self::Error>;
}

/// A [`Service`] using the a [`Router`] `R` to redirect messages to specific routes.
/// A [`Service`] using the [`Router`] `R` to redirect messages to specific routes.
///
/// The `Protocol` parameter is used to determine
/// The `Protocol` parameter is used to determine the serialization of errors.
pub struct RoutingService<R, Protocol> {
router: R,
_protocol: PhantomData<Protocol>,
Expand Down

0 comments on commit bf3fbc2

Please sign in to comment.