Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adopt AEP 231 - Batch Get #177

Merged
merged 15 commits into from
Oct 25, 2024
180 changes: 177 additions & 3 deletions aep/general/0231/aep.md.j2
Original file line number Diff line number Diff line change
@@ -1,5 +1,179 @@
# Batch methods: Get

**Note:** This AEP has not yet been adopted. See
[this GitHub issue](https://github.com/aep-dev/aep.dev/issues/42) for more
information.
Some APIs need to allow users to get a specific set of resources at a
consistent time point (e.g. using a read transaction). A batch get method
mkistler marked this conversation as resolved.
Show resolved Hide resolved
provides this functionality.

## Guidance

APIs **may** support batch get to retrieve a consistent set of resources.

- The method's name **must** begin with `BatchGet`. The remainder of the method
name **must** be the plural form of the resource being retrieved.
- The HTTP verb **must** be `GET`.
- The HTTP URI **must** end with `:batchGet`.
- The URI path **must** represent the collection for the resource, matching the
collection used for simple CRUD operations. If the operation spans parents, a
[wilcard](./reading-across-collections) **may** be accepted.
- There **must not** be a request body.
- If a GET request contains a body, the body **must** be ignored, and **must
not** cause an error.

### Request

The request for a batch get method **should** be specified with the following
pattern:

- The request **must** include an array field which accepts the resource paths
specifying the resources to retrieve. The field **must** be named `paths`.
- If no resource paths are provided, the API **should** error with
`INVALID_ARGUMENT`.
- The parameter **must** be required.
- The documentation for the parameter **should** include the
[resource type](./paths) that it references.
- The parameter should define the pattern of the resource path values.
toumorokoshi marked this conversation as resolved.
Show resolved Hide resolved
- The parameter should define the maximum number of paths allowed.
- Batch Get **should not** support pagination because transactionality across
API calls would be extremely difficult to implement or enforce, and the
request defines the exact scope of the response anyway.
- The request **must not** contain any other required parameters, and **should
not** contain other optional parameters except those described in this or
another AEP.

{% tab proto -%}

```proto
rpc BatchGetBooks(BatchGetBooksRequest) returns (BatchGetBooksResponse) {
option (google.api.http) = {
get: "/v1/{parent=publishers/*}/books:batchGet"
};
}

message BatchGetBooksRequest {
// The parent resource shared by all books being retrieved.
// Format: publishers/{publisher}
// If this is set, the parent of all of the books specified in `paths`
// must match this field.
string parent = 1 [
(google.api.resource_reference) = {
child_type: "library.com/Book"
}];

// The paths of the books to retrieve.
// A maximum of 1000 books can be retrieved in a batch.
// Format: publishers/{publisher}/books/{book}
repeated string paths = 2 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {
type: "library.com/Book"
}];
}
```

- The request schema **must** match the method name, with `Request` suffix.
- A `parent` field **should** be included, unless the resource being retrieved
is a top-level resource, to facilitate inclusion in the URI as well to permit
a single permissions check. If a caller sets this field, and the parent
collection in the path of any resource being retrieved does not match, the
request **must** fail.
- This field **should** be required if only 1 parent per request is allowed.
- The field **should** identify the [resource type][aep-122-parent] that it
references.
- The comment for the field **should** document the resource pattern.
- There **must not** be a body key in the `google.api.http` annotation.

{% tab oas %}
mkistler marked this conversation as resolved.
Show resolved Hide resolved

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

- The `paths` parameter **must** be a query parameter which accepts an array of
resource paths specifying the resources to retrieve.
- If no resource paths are provided, the API **should** error with status
code `400 Bad Request`.
- If the collection in the path of any resource does not match the collection
of the request URL, the request **must** fail.
- The method definition **must not** have a `requestBody` defined.

{% endtabs %}

### Response

The response for a batch get method **must** be specified with the following
pattern:

- The response schema **must** match the method name, with `Response` suffix.
- The response schema **must** have a single array property where each item is
either a retrieved resource or an error structure describing an error that
occurred attempting to retrieve the resource. The error alternative would
only be present for non-transactional batch gets.
- The order of resources/error objects in the response **must** be the same as
the paths in the request.
- The array of resources **must** be named `results` and contain resources with
no additional wrapping.
- There **must not** be a `nextPageToken` field as batch get operations are not
pageable.

{% tab proto -%}

```proto
message BatchGetBooksResponse {
// Books requested.
repeated Book books = 1;
}
```

{% tab oas %}

{% sample 'batchget.oas.yaml', '/publishers/{publisherId}/books:BatchGet' %}

Example response body:

```json
{
"results": [
{
"name": "publishers/lacroix/books/les-mis",
"isbn": "978-037-540317-0",
"title": "Les Misérables",
"authors": ["Victor Hugo"],
"rating": 9.6
},
{
"type": "https://datatracker.ietf.org/doc/html/rfc9110#name-404-not-found",
"title": "The resource is not available"
}
{
"name": "publishers/lacroix/books/hunchback-of-notre-dame",
"isbn": "978-140-274575-1",
"title": "The Hunchback of Notre Dame",
"authors": ["Victor Hugo"],
"rating": 9.3
}
]
}
```

{% endtabs %}

### Support for transactional get

The batch get method may support a transactional form of operation where the
get either succeeds for all requested resources or fails. When supported, the
method must define a boolean parameter `transactional` that the user must
specify with the value `true` to request a transactional operation.

## Changelog

- **2024-04-22:** Adopt from Google AIP https://google.aip.dev/231 with the
following changes:
- Dropped the "nested requests" pattern.
mkistler marked this conversation as resolved.
Show resolved Hide resolved
- Changed the response schema to an object with `results` array property.
- Made transactional operation optional and controlled by asTransaction
parameter.

<!-- Links -->

[aep-122-paths]: ./0122.md#fields-representing-resource-paths
[aep-122-parent]: ./0122.md#fields-representing-a-resources-parent
[aep-132]: https://aep.dev/132
[get-request]: ./0131.md#get-request
4 changes: 2 additions & 2 deletions aep/general/0231/aep.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
id: 231
state: reviewing
state: approved
slug: batch-get
created: 2023-01-22
created: 2024-04-22
placement:
category: batch-methods
71 changes: 71 additions & 0 deletions aep/general/0231/batchget.oas.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
openapi: 3.0.3
info:
title: Library
version: 1.0.0
paths:
/publishers/{publisherId}/books:BatchGet:
parameters:
- name: publisherId
in: path
required: true
schema:
type: string
get:
operationId: BatchGetBooks
description: Get multiple books in a batch.
parameters:
- name: paths
in: query
required: true
description: >-
The paths of the books to retrieve. Format:
publishers/{publisherId}/books/{book}
schema:
type: array
minItems: 1
maxItems: 1000
items:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
oneOf:
- $ref: '#/components/schemas/Book'
- $ref: '#/components/schemas/Error'
components:
schemas:
Book:
description: A representation of a single book.
type: object
properties:
name:
type: string
description: |
The name of the book.
Format: publishers/{publisher}/books/{book}
isbn:
type: string
description: |
The ISBN (International Standard Book Number) for this book.
title:
type: string
description: The title of the book.
authors:
type: array
items:
type: string
description: The author or authors of the book.
rating:
type: number
format: float
description: The rating assigned to the book.
Error:
type: object
Loading