Unverified Commit 72a5c5b3 authored by Russell Cohen's avatar Russell Cohen Committed by GitHub
Browse files

Add initial set of docs (#313)

* Add initial set of docs

* More design documentation updates

* Updates to the docs

* Update tenets again to remove the dependeny tenet

* Remove `!`

* Add more design documentation

* More updates to tenets

* More tenets updates

* tenets typo

* Rephrase as 'AWS SDK for Rust'

* rephrase tenets
parent 72674757
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@ Smithy code generators for Rust

The nightly SDK build can be found under `Actions -> CI (take latest run) -> Artifacts`

[Design documentation (WIP)](https://ubiquitous-robot-7dc8d16d.pages.github.io/)

**All internal and external interfaces are considered unstable and subject to change without notice.**

## Setup
@@ -31,5 +33,10 @@ pre-commit install

### Project Layout
* `aws`: AWS specific codegen & Rust code (signing, endpoints, customizations, etc.)
  Common commands:
     * `./gradlew :aws:sdk:assemble`: Generate (but do not test / compile etc.) a fresh SDK into `sdk/build/aws-sdk`
     * `./gradlew :aws:sdk:test`: Generate & run all tests for a fresh SDK
     * `./gradlew :aws:sdk:{cargoCheck, cargoTest, cargoDocs, cargoClippy}`: Generate & run specified cargo command.
* `codegen`: Whitelabel Smithy code generation
* `codegen-test`: Smithy protocol test generation & integration tests for Smithy whitelabel code
* [`design`](design): Design documentation. See the [design/README.md](design/README.md) for details about building / viewing.

design/README.md

0 → 100644
+8 −0
Original line number Diff line number Diff line
Design docs are hosted [here](https://ubiquitous-robot-7dc8d16d.pages.github.io/).

To render design docs locally:
```
cargo install mdbook
mdbook serve &
open http://localhost:3000
```
+11 −3
Original line number Diff line number Diff line
# Summary
- [Design Overview](./overview.md)
- [Tenets](./tenets.md)
- [Design FAQ](./faq.md)
- [Transport](transport/overview.md)
  - [Http Operations](transport/operation.md)
  - [HTTP middleware](transport/middleware.md)

- [Http Operations](./operation.md)
- [Endpoint Resolution](./endpoint.md)
- [HTTP middleware](./middleware.md)
- [Smithy](./smithy/overview.md)
    - [Simple Shapes](./smithy/simple_shapes.md)
    - [Recursive Shapes](./smithy/recursive_shapes.md)
    - [Aggregate Shapes](./smithy/aggregate_shapes.md)
    - [Endpoint Resolution](smithy/endpoint.md)
+0 −50
Original line number Diff line number Diff line
# Endpoint Resolution

## Requirements
The core codegen generates HTTP requests that do not contain an authority, scheme or post. These properties must be set later based on configuration. Existing AWS services have a number of requirements that increase the complexity:

1. Endpoints must support manual configuration by end users:
```rust
let config = dynamodb::Config::builder()
    .endpoint(StaticEndpoint::for_uri("http://localhost:8000"))
```

When a user specifies a custom endpoint URI, _typically_ they will want to avoid having this URI mutated by other endpoint discovery machinery.

2. Endpoints must support being customized on a per-operation basis by the endpoint trait. This will prefix the base endpoint, potentially driven by fields of the operation. [Docs](https://awslabs.github.io/smithy/1.0/spec/core/endpoint-traits.html#endpoint-trait)

3. Endpoints must support being customized by [endpoint discovery](https://awslabs.github.io/smithy/1.0/spec/aws/aws-core.html#client-endpoint-discovery). A request, customized by a predefined set of fields from the input operation is dispatched to a specific URI. That operation returns the endpoint that should be used. Endpoints must be cached by a cache key containing:
```
(access_key_id, [all input fields], operation)
```
Endpoints retrieved in this way specify a TTL.

4. Endpoints must be able to customize the signing (and other phases of the operation). For example, requests sent to a global region will have a region set by the endpoint provider.


## Design

Configuration objects for services _must_ contain an `Endpoint`. This endpoint may be set by a user or it will default to the `endpointPrefix` from the service definition. In the case of endpoint discovery, _this_ is the endpoint that we will start with.

During operation construction (see [Operation Construction](operation.md#operation-construction)) an `EndpointPrefix` may be set on the property bag. The eventual endpoint middleware will search for this in the property bag and (depending on the URI mutability) utilize this prefix when setting the endpoint.

In the case of endpoint discovery, we envision a different pattern:
```rust
// EndpointClient manages the endpoint cache
let (tx, rx) = dynamodb::EndpointClient::new();
let client = aws_hyper::Client::new();
// `endpoint_req` is an operation that can be dispatched to retrieve endpoints
// During operation construction, the endpoint resolver is configured to be `rx` instead static endpoint
// resolver provided by the service.
let (endpoint_req, req) = GetRecord::builder().endpoint_disco(rx).build_with_endpoint();
// depending on the duration of endpoint expiration, this may be spawned into a separate task to continuously
// refresh endpoints.
if tx.needs(endpoint_req) {
    let new_endpoint = client.
        call(endpoint_req)
        .await;
    tx.send(new_endpoint)
}
let rsp = client.call(req).await?;
```

We believe that this design results in an SDK that both offers customers more control & reduces the likelihood of bugs from nested operation dispatch. Endpoint resolution is currently extremely rare in AWS services so this design may remain a prototype while we solidify other behaviors.

design/src/faq.md

0 → 100644
+10 −0
Original line number Diff line number Diff line
# Design FAQ
### What is Smithy?
Smithy is the interface design language used by AWS services. `smithy-rs` allows users to generate a Rust client for any Smithy based service (pending protocol support), including those outside of AWS.

### Why is there one crate per service?
1. Compilation time: Although it's possible to use cargo features to conditionally compile individual services, we decided that this added significant complexity to the generated code. In Rust the "unit of compilation" is a Crate, so by using smaller crates we can get better compilation parallelism.

2. Versioning: It is expected that over time we may major-version-bump individual services. New updates will be pushed for _some_ AWS service nearly every day. Maintaining separate crates allows us to only increment versions for the relevant pieces that change.

It is worth noting that this isn't a set-in-stone design decision. A parent crate may be even be created at some point!
Loading