diff --git a/aep/general/0231/aep.md.j2 b/aep/general/0231/aep.md.j2 index 983884b9..a76ea427 100644 --- a/aep/general/0231/aep.md.j2 +++ b/aep/general/0231/aep.md.j2 @@ -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. + + + +[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 diff --git a/aep/general/0231/aep.yaml b/aep/general/0231/aep.yaml index 997d2e00..96b556cd 100644 --- a/aep/general/0231/aep.yaml +++ b/aep/general/0231/aep.yaml @@ -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 diff --git a/aep/general/0231/batchget.oas.yaml b/aep/general/0231/batchget.oas.yaml new file mode 100644 index 00000000..085040fd --- /dev/null +++ b/aep/general/0231/batchget.oas.yaml @@ -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