Skip to content

Commit

Permalink
feat(231): adopt batch Get (#177)
Browse files Browse the repository at this point in the history
Importing batch-get from aip.dev.
---------

Co-authored-by: Richard Frankel <[email protected]>
Co-authored-by: Yusuke Tsutsumi <[email protected]>
  • Loading branch information
3 people authored Oct 25, 2024
1 parent 2257780 commit 39e5180
Show file tree
Hide file tree
Showing 3 changed files with 250 additions and 5 deletions.
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
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.
- 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 %}

{% 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.
- 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

0 comments on commit 39e5180

Please sign in to comment.