Skip to content

Commit

Permalink
fix(methods): remove management plane, require strong consistency (#222)
Browse files Browse the repository at this point in the history
The introduction of the concept of management plane and data plane
and it's subjective definition in the AEPs was leading to ambiguous
guidance. Removing the mention of those concepts until a clearer
criteria can be established.

This change requires that a decision must be made for strong
consistency. As operations that are not strongly consistent
can result in manual per-resource patches for declarative clients,
require strong consistency for all standard methods.
  • Loading branch information
toumorokoshi authored Nov 2, 2024
1 parent 5631df6 commit d5f3482
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 31 deletions.
22 changes: 13 additions & 9 deletions aep/general/0121/aep.md.j2
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,21 @@ patterns, such as database transactions, import and export, or data analysis.

### Strong Consistency

For methods that operate on the [management plane][], the completion of those
operations (either successful or with an error,
[long-running][long-running-requests] or synchronous) **must** mean that the
state of the resource's existence and all user-settable values have reached a
steady-state.
A method is strongly consistent if, upon completion of a request of that method
(regardless of whether the request is successful,
[long-running][long-running-requests] or synchronous), all user-settable fields
will return the same value on any subsequent requests until another request
which mutates the resource is completed.

[Output only][output only] values unrelated to the resource [state][]
**should** also have reached a steady-state.
[Output only][output only] fields unrelated to the resource [state][] **should**
also return the same value on each subsequent request until another request
which mutates the resource is completed.

Examples include:
- An output-only field that takes so long to reach a steady-state that it would
negatively impact the user experience of the request (e.g. an hour-long instantiation
of a VM cluster).

Examples of strong consistency include:

- Following a successful create that is is latest mutation on a resource, a get
request for a resource **must** return the resource.
Expand Down Expand Up @@ -141,7 +146,6 @@ turn do not increase resource management complexity.
[get]: ./0131.md
[list]: ./0132.md
[long-running-requests]: ./0151.md
[management plane]: ./0111.md#management-plane
[output only]: ./0203.md#output-only
[rest]: https://en.wikipedia.org/wiki/Representational_state_transfer
[resource references]: ./0122.md#fields-representing-another-resource
Expand Down
22 changes: 8 additions & 14 deletions aep/general/0133/aep.md.j2
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,7 @@ rpc CreateBook(CreateBookRequest) returns (Book) {
- There **should** be exactly one `google.api.method_signature` annotation,
with a value of `"parent,{resource},id"`, or "`"parent,{resource}"` if the
resource ID is not required.
- If the API is operating on the [management plane][], the operation should have
[strong consistency][]: the completion of a create operation **must** mean
that all user-settable values and the existence of the resource have reached a
steady-state and reading resource state returns a consistent response.
- The operation **must** have [strong consistency][].

{% tab oas %}

Expand All @@ -72,8 +69,7 @@ rpc CreateBook(CreateBookRequest) returns (Book) {

Create methods implement a common request message pattern:

- An `id` field **must** be included for management plane resources, and
**should** be included for data plane resources.
- An `id` field **should** be supported.
- The resource field **must** be included and **must** map to the POST body.
- The request message **must not** contain any other required fields and
**should not** contain other optional fields except those described in this
Expand Down Expand Up @@ -148,16 +144,15 @@ rpc CreateBook(CreateBookRequest) returns (aep.api.Operation) {

### User-specified IDs

An API **must** allow a user to specify the ID component of a resource (the
last segment of the resource path) on creation if the API is operating on the
[management plane][].
An API **should** allow a user to specify the ID component of a resource: not
doing so introduces a non-idempotent request in the API, as sending the same
payload results in creating a new resource each time.

On the [data plane][], an API **should** allow a user to specify the ID.
Exceptional cases should have the following behavior:

- The data plane resource allows identical records without a need to
disambiguate between the two (e.g. rows in a table with no primary key).
- The data plane resource will not be exposed in [Declarative clients][].
- The resource allows identical records without a need to disambiguate between
the two (e.g. rows in a table with no primary key).
- The resource will not be exposed in [Declarative clients][].

An API **may** allow the `id` field to be optional, and give the resource a
system-generated ID if one is not specified.
Expand Down Expand Up @@ -233,7 +228,6 @@ path and use it in references from other resources.
[aep-203]: ./0203.md
[aep-210]: ./0210.md
[data plane]: ./0111.md#data-plane
[management plane]: ./0111.md#management-plane
[errors]: ./0193.md
[field_behavior]: ./203.md
[Declarative clients]: ./0003.md#declarative-clients
Expand Down
47 changes: 45 additions & 2 deletions aep/general/0134/aep.md.j2
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Update methods are specified using the following pattern:
itself.
- The method **should** support partial resource update, and the HTTP verb
**should** be `PATCH`.
- The operation **must** have [strong consistency][].

{% tab proto %}

Expand Down Expand Up @@ -190,7 +191,6 @@ rpc UpdateBook(UpdateBookRequest) returns (aep.api.Operation) {

{% endtabs %}

### Create or update

If the service uses client-assigned resource paths, `Update` methods **may**
expose a `bool allow_missing` field, which will cause the method to succeed in
Expand Down Expand Up @@ -229,6 +229,50 @@ More specifically, the `allow_missing` flag triggers the following behavior:
The user **must** have the update permissions to call `Update` even with
`allow_missing` set to `true`.

If the service uses client-assigned resource paths, `Update` methods **may**
expose a `bool allow_missing` field, which will cause the method to succeed in
the event that the user attempts to update a resource that is not present (and
will create the resource in the process):

{% tab proto %}

```proto
message UpdateBookRequest {
// The book to update.
//
// The book's `path` field is used to identify the book to be updated.
// Format: publishers/{publisher}/books/{book}
Book book = 1 [(google.api.field_behavior) = REQUIRED];

// The list of fields to be updated.
google.protobuf.FieldMask update_mask = 2;

// If set to true, and the book is not found, a new book will be created.
// In this situation, `update_mask` is ignored.
bool allow_missing = 3;
}
```

{% tab oas %}

**Note:** OAS example not yet written.

{% endtabs %}

More specifically, the `allow_missing` flag triggers the following behavior:

- If the method call is on a resource that does not exist, the resource is
created. All fields are applied regardless of any provided field mask.
- However, if any required fields are missing or fields have invalid values,
an `INVALID_ARGUMENT` error is returned.
- If the method call is on a resource that already exists, and all fields
match, the existing resource is returned unchanged.
- If the method call is on a resource that already exists, only fields declared
in the field mask are updated.

The user **must** have the update permissions to call `Update` even with
`allow_missing` set to `true`.

### Etags

An API may sometimes need to allow users to send update requests which are
Expand Down Expand Up @@ -312,7 +356,6 @@ unless `allow_missing` is set to `true`.
[aep-203]: ./0203.md
[create]: ./0133.md
[errors]: ./0193.md
[management plane]: ./0111.md#management-plane
[permission-denied]: ./0193.md#permission-denied
[state fields]: ./0216.md
[strong consistency]: ./0121.md#strong-consistency
Expand Down
9 changes: 4 additions & 5 deletions aep/general/0135/aep.md.j2
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ The Delete method **should** succeed if and only if a resource was present and
was successfully deleted. If the resource did not exist, the method **should**
send a `404 Not found` (`NOT_FOUND`) error.

If the API is operating on the [Management Plane][], the method should have
[strong consistency][]: the completion of a delete method **must** mean that
the existence of the resource has reached a steady-state and reading resource
state returns a consistent `404 Not found` (`NOT_FOUND`) response.
The method **must** have [strong consistency][]: the completion of a delete
method **must** mean that the existence of the resource has reached a
steady-state and reading resource state returns a consistent `404 Not found`
(`NOT_FOUND`) response.

Delete methods are specified using the following pattern:

Expand Down Expand Up @@ -230,7 +230,6 @@ exist, the service **must** error with `404 Not found` (`NOT_FOUND`).
[aep-203]: ./0203.md
[aep-214]: ./0214.md
[aep-216]: ./0216.md
[management plane]: ./0111.md#management-plane
[strong consistency]: ./0121.md#strong-consistency
[etag]: ./0134.md#etags
[RFC 9110]: https://www.rfc-editor.org/rfc/rfc9110.html#name-delete
Expand Down
3 changes: 2 additions & 1 deletion aep/general/0154/aep.md.j2
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ current ETag. If the `If-Match` header value does not match the ETag, the
service **must** reply with an HTTP 412 error.

If the user omits the `If-Match` header, the service **should** permit the
request. However, services with strong consistency or parallelism requirements
request. However, services with [strong consistency][] or parallelism requirements
**may** require users to send ETags all the time and reject the request with an
HTTP 400 error if it does not contain an ETag.

Expand Down Expand Up @@ -113,3 +113,4 @@ not equivalent to the old one).
- **2019-09-23**: Changed the title to "resource freshness validation".

[rfc 7232]: https://tools.ietf.org/html/rfc7232#section-2.3
[strong consistency]: ./0121.md#strong-consistency

0 comments on commit d5f3482

Please sign in to comment.