Skip to content

Commit

Permalink
fix(151): removing duplicate status code guidance
Browse files Browse the repository at this point in the history
The guidance around LROs described the 202 status code
for gRPC, which is not relevant. Since this is already
documented in the "Interface Definitions" section, removing
the duplicate guidance seemed the best option - it will
minimize future maintenance.

Helps address aep-dev#224.
  • Loading branch information
toumorokoshi committed Oct 19, 2024
1 parent 0982852 commit 472592c
Showing 1 changed file with 67 additions and 81 deletions.
148 changes: 67 additions & 81 deletions aep/general/0151/aep.md.j2
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,89 @@ return some kind of promise to the user, and allow the user to check back in
later.

The long-running request pattern is roughly analogous to a [Future][] in Python
or Java, or a [Node.js Promise][]. Essentially, the user is given a token that
can be used to track progress and retrieve the result.
or Java, or a [Node.js Promise][]: the user is given a token that can be used to
track progress and retrieve the result.

## Guidance

Operations that might take a significant amount of time to complete **should**
return a `202 Accepted` response along with an `Operation` resource that can be
used to track the status of the request and ultimately retrieve the result.
return an `Operation` resource that can be used to track the status of the
request and ultimately retrieve the result.

Any single operation defined in an API surface **must** either _always_ return
`202 Accepted` along with an `Operation`, or _never_ do so. A service **must
not** return a `200 OK` response with the result if it is "fast enough", and
`202 Accepted` if it is not fast enough, because such behavior adds significant
burdens for clients.
A single method defined in an API surface **must** either _always_ return an
`Operation`, or _never_ do so. As an example, a long-running operation **must
not** return a response with the result of the operation if the operation
completes quickly.

**Note:** User expectations can vary on what is considered "a significant
amount of time" depending on what work is being done. A good rule of thumb is
10 seconds.
### Interface Definitions

### Operation representation
{% tab proto %}

The response to a long-running request **must** be an [`Operation`][Operation].
When using protocol buffers, the common component
[`aep.api.Operation`][aep.api.Operation] is used.

{% tab proto %}
{% sample 'lro.proto', 'rpc WriteBook' %}

Protocol buffer APIs **must** use the common component
[`aep.api.Operation`][aep.api.Operation].
- The response type **must** be `aep.api.Operation`. The `Operation` proto
definition **should not** be copied into individual APIs; prefer to use a
single copy (in monorepo code bases), or remote dependencies via a tool like
[Buf][buf.build].
- The response **must not** be a streaming response.
- The method **must** include a [`aep.api.operation_info`][lro] annotation,
which **must** define both response and metadata types.
- The response and metadata types **must** be defined in the file where the
RPC appears, or a file imported by that file.
- If the response and metadata types are defined in another package, the
fully-qualified message name **must** be used.
- The response type **should not** be `google.protobuf.Empty` (except for
[`Delete`][aep-135] methods), unless it is certain that response data will
_never_ be needed. If response data might be added in the future, define an
empty message for the RPC response and use that.
- The metadata type is used to provide information such as progress, partial
failures, and similar information on each `GetOperation` call. The metadata
type **should not** be `google.protobuf.Empty`, unless it is certain that
metadata will _never_ be needed. If metadata might be added in the future,
define an empty message for the RPC metadata and use that.
- APIs with messages that return `Operation` **must** implement the
`GetOperation` method of the [`Operations`][lro] service, and **may**
implement the other methods defined in that service. Individual APIs **must
not** define their own interfaces for long-running operations to avoid
inconsistency.

{% tab oas %}

OpenAPI services **must** use this [`JSON Schema Operation`][JSON Schema
Operation] schema.
{% sample 'lro.oas.yaml', 'paths' %}

- `202` **must** be the only success status code defined.
- The `202` response **must** define an `application/json` response body and no
other response content types.
- The response body schema **must** be an object with `path`, `done`, `error`,
and `response` properties as described above for an `Operation`.
- The response body schema **may** contain an object property named `metadata`
to hold service-specific metadata associated with the operation, for example
progress information and common metadata such as create time. The service
**should** define the contents of the `metadata` object in a separate schema,
which **should** specify `additionalProperties: true` to allow for future
extensibility.
- The `response` property **must** be a schema that defines the success
response for the operation. For an operation that typically gives a
`204 No Content` response, such as a `Delete`, `response` should be defined
as an empty object schema. For a standard `Get/Create/Update` operation,
`response` should be a representation of the resource.
- If a service has any long running operations, the service **must** define an
`Operation` resource with a `list` operation to retrieve a potentially
filtered list of operations and a `get` operation to retrieve a specific
operation by its `path`.

{% endtabs %}

### When to use an long-running operation

User expectations can vary on what is considered a significant amount of time
depending on what work is being done. Generally, a request **should** complete
10 seconds, as the longer period of time may block clients or by perceived by a
user as a hung request.

### Querying an operation

The service **must** provide an endpoint to query the status of the operation,
Expand Down Expand Up @@ -96,68 +144,6 @@ Errors that occur over the course of a request **may** be placed in the
metadata message. The errors themselves **must** still be represented with a
canonical error object.

## Interface Definitions

{% tab proto %}

When using protocol buffers, the common component
[`aep.api.Operation`][aep.api.Operation] is used.

{% sample 'lro.proto', 'rpc WriteBook' %}

- The response type **must** be `aep.api.Operation`. The `Operation` proto
definition **should not** be copied into individual APIs; prefer to use a
single copy (in monorepo code bases), or remote dependencies via a tool like
[Buf][buf.build].
- The response **must not** be a streaming response.
- The method **must** include a [`aep.api.operation_info`][lro] annotation,
which **must** define both response and metadata types.
- The response and metadata types **must** be defined in the file where the
RPC appears, or a file imported by that file.
- If the response and metadata types are defined in another package, the
fully-qualified message name **must** be used.
- The response type **should not** be `google.protobuf.Empty` (except for
[`Delete`][aep-135] methods), unless it is certain that response data will
_never_ be needed. If response data might be added in the future, define an
empty message for the RPC response and use that.
- The metadata type is used to provide information such as progress, partial
failures, and similar information on each `GetOperation` call. The metadata
type **should not** be `google.protobuf.Empty`, unless it is certain that
metadata will _never_ be needed. If metadata might be added in the future,
define an empty message for the RPC metadata and use that.
- APIs with messages that return `Operation` **must** implement the
`GetOperation` method of the [`Operations`][lro] service, and **may**
implement the other methods defined in that service. Individual APIs **must
not** define their own interfaces for long-running operations to avoid
inconsistency.

{% tab oas %}

{% sample 'lro.oas.yaml', 'paths' %}

- `202` **must** be the only success status code defined.
- The `202` response **must** define an `application/json` response body and no
other response content types.
- The response body schema **must** be an object with `path`, `done`, `error`,
and `response` properties as described above for an `Operation`.
- The response body schema **may** contain an object property named `metadata`
to hold service-specific metadata associated with the operation, for example
progress information and common metadata such as create time. The service
**should** define the contents of the `metadata` object in a separate schema,
which **should** specify `additionalProperties: true` to allow for future
extensibility.
- The `response` property **must** be a schema that defines the success
response for the operation. For an operation that typically gives a
`204 No Content` response, such as a `Delete`, `response` should be defined
as an empty object schema. For a standard `Get/Create/Update` operation,
`response` should be a representation of the resource.
- If a service has any long running operations, the service **must** define an
`Operation` resource with a `list` operation to retrieve a potentially
filtered list of operations and a `get` operation to retrieve a specific
operation by its `path`.

{% endtabs %}

<!-- prettier-ignore-start -->
[google.rpc.Status]: https://github.com/googleapis/api-common-protos/blob/master/google/rpc/S.proto
[lro]: https://github.com/aep-dev/aep/blob/main/proto/aep-api/aep/api/operations.proto
Expand Down

0 comments on commit 472592c

Please sign in to comment.