Skip to main content

Module operation

Module operation 

Source
Expand description

The shape of a Smithy operation is modelled by the OperationShape trait. Its associated types OperationShape::Input, OperationShape::Output, and OperationShape::Error map to the structures representing the Smithy inputs, outputs, and errors respectively. When an operation error is not specified OperationShape::Error is Infallible.

We generate a marker struct for each Smithy operation and implement OperationShape on them. This is used as a helper - providing static methods and parameterizing other traits.

The model

operation GetShopping {
   input: CartIdentifier,
   output: ShoppingCart,
   errors: [...]
}

is identified with the implementation

pub struct GetShopping;

impl OperationShape for GetShopping {
    const ID: ShapeId = ShapeId::new("namespace#GetShopping", "namespace", "GetShopping");

    type Input = CartIdentifier;
    type Output = ShoppingCart;
    type Error = GetShoppingError;
}

The behavior of a Smithy operation is encoded by a Service. The OperationShape types can be used to construct specific operations using OperationShapeExt::from_handler and OperationShapeExt::from_service methods. The from_handler constructor takes a Handler whereas the from_service takes a OperationService. Both traits serve a similar purpose - they provide a common interface over a class of structures.

§Handler

The Handler trait is implemented by all async functions which accept OperationShape::Input as their first argument, the remaining arguments implement FromParts, and return either OperationShape::Output when OperationShape::Error is Infallible or Result<OperationShape::Output,OperationShape::Error>. The following are examples of async functions which implement Handler:

// Simple handler where no error is modelled.
async fn handler_a(input: CartIdentifier) -> ShoppingCart {
    todo!()
}

// Handler with an extension where no error is modelled.
async fn handler_b(input: CartIdentifier, ext: Extension<Context>) -> ShoppingCart {
    todo!()
}

// More than one extension can be provided.
async fn handler_c(input: CartIdentifier, ext_1: Extension<Context>, ext_2: Extension<ExtraContext>) -> ShoppingCart {
    todo!()
}

// When an error is modelled we must return a `Result`.
async fn handler_d(input: CartIdentifier, ext: Extension<Context>) -> Result<ShoppingCart, GetShoppingError> {
    todo!()
}

§OperationService

Similarly, the OperationService trait is implemented by all Service<(Op::Input, ...)> with Response = Op::Output, and Error = Op::Error.

The following are examples of Services which implement OperationService:

  • Service<CartIdentifier, Response = ShoppingCart, Error = Infallible>.
  • Service<(CartIdentifier, Extension<Context>), Response = ShoppingCart, Error = GetShoppingCartError>.
  • Service<(CartIdentifier, Extension<Context>, Extension<ExtraContext>), Response = ShoppingCart, Error = GetShoppingCartError).

Notice the parallels between OperationService and Handler.

§Constructing an Operation

The following is an example of using both construction approaches:

// Construction of an `Operation` from a `Handler`.

async fn op_handler(input: CartIdentifier) -> Result<ShoppingCart, GetShoppingError> {
    todo!()
}

let operation = GetShopping::from_handler(op_handler);

// Construction of an `Operation` from a `Service`.

pub struct OpService;

impl Service<CartIdentifier> for OpService {
    type Response = ShoppingCart;
    type Error = GetShoppingError;
    type Future = OpFuture;

    fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
        todo!()
    }

    fn call(&mut self, request: CartIdentifier) -> Self::Future {
        todo!()
    }
}

let operation = GetShopping::from_service(OpService);

§Upgrading Smithy services to HTTP services

Both Handler and OperationService accept and return Smithy model structures. They are converted to a canonical form Service<(Op::Input, Exts), Response = Op::Output, Error = Op::Error>. The UpgradePlugin acts upon such services by converting them to Service<http::Request, Response = http::Response, Error = Infallible> by applying serialization/deserialization and validation specified by the Smithy contract.

The UpgradePlugin, being a Plugin, is parameterized by a protocol. This allows for upgrading to Service<http::Request, Response = http::Response, Error = Infallible> to be protocol dependent.

Structs§

DynStreamingUpgrade
Upgrade service for a schema operation with a streaming input or output.
DynStreamingUpgradePlugin
Schema-driven, protocol-neutral HTTP upgrade plugin for operations with a streaming member.
DynUpgrade
Upgrade service for a non-streaming schema operation.
DynUpgradePlugin
Schema-driven, protocol-neutral HTTP upgrade plugin for operations without streaming members.
IntoService
A [Service] provided for every Handler.
MissingFailure
A [Service] which always returns an internal failure message and logs an error.
Normalize
A [Service] normalizing the request type of a OperationService.
SchemaMissingFailure
Missing-handler fallback using the protocol selected by schema routing.
Upgrade
A [Service] responsible for wrapping an operation [Service] accepting and returning Smithy types, and converting it into a [Service] accepting and returning [http] types.
UpgradeFuture
The [Service::Future] of Upgrade.
UpgradePlugin
A Plugin responsible for taking an operation [Service], accepting and returning Smithy types and converting it into a [Service] taking and returning [http] types.

Traits§

Handler
A utility trait used to provide an even interface for all operation handlers.
HandlerExt
An extension trait for Handler.
OperationService
A utility trait used to provide an even interface for all operation services.
OperationServiceExt
An extension trait of OperationService.
OperationShape
Models the Smithy Operation shape.
OperationShapeExt
An extension trait over OperationShape.
SchemaOperationShape
Associates a generated operation marker with its schema descriptor.
StreamingOperationShape
The generated glue between the HTTP bodies and the streaming members of an operation with an event stream or streaming blob on either side.

Type Aliases§

StreamingInputFuture
The future returned by StreamingOperationShape::deserialize_streaming_input.