# API module

<!-- TOC -->
* [API module](#api-module)
  * [Design principles](#design-principles)
  * [Why not just use an ID to identify a resource, but instead use a name formatted as `publishers/123/books/les-miserables`?](#why-not-just-use-an-id-to-identify-a-resource-but-instead-use-a-name-formatted-as-publishers123booksles-miserables-)
  * [Disallow embedding of resources](#disallow-embedding-of-resources)
  * [Request message of a method that acts on an already-existing resource](#request-message-of-a-method-that-acts-on-an-already-existing-resource)
  * [Request message of a method that creates a new resource or list resources](#request-message-of-a-method-that-creates-a-new-resource-or-list-resources)
  * [Extract resource name from HTTP path](#extract-resource-name-from-http-path)
  * [Declarative-friendly APIs](#declarative-friendly-apis)
<!-- TOC -->

## [Design principles](https://google.aip.dev/121)

- Resource-oriented. Hierarchical resources are the fundamental building blocks of an API.
    - Standard methods, which are (Get, List, Create, Update, Delete), cover the most common operations.
- Consistent. For methods operating on the management plane, the completion of these operations (whether successful, failed) must ensure that:
    - All values unrelated to the resource state are finalized.
    - The existence of resources is consistent.
- Concise and specific. Ensure methods are unambiguous and narrowly defined, avoiding wide interfaces that can perform multiple actions.
    - For example, use specific methods like ListClustersById([]ids) instead of broad ones like ListClusters([]tenants, []projects, []ids).
- Automated. The development and release process of the Open API should be fully automated. This includes, but is not limited to:
    - API definition sourcefile(*.proto) linting
    - Breaking change checks
    - E2E tests
    - Delivering Swagger JSON to the user documentation team

As mentioned in Open API Milestone 2 : High level Guideline,
RDG has decided that TiDB Open API should adhere to Google's API Improvement Proposals (AIPs).
These AIPs are very detailed; please refer to the official website for specific content.

During implementation, we have followed most of the AIPs rules but have omitted some minor ones. The key differences are as follows:
- While AIPs require resources to be referred to by resource name, we have decided to refer to them by resource ID. This decision affects the definition of association fields in the resource itself and their related request bodies.
    - Rationale: [explain the reasoning]
    - Example: [provide an example]
- While AIPs require using field_mask in UPDATE requests to specify which fields should be modified by the user input, we decided not to use field_mask. Instead, we place user input values at the top level of the request body.
    - Rationale: [explain the reasoning]
    - Example: [provide an example]

## [Why not just use an ID to identify a resource, but instead use a name formatted as `publishers/123/books/les-miserables`?](https://google.aip.dev/122#guidance)

Resource name components should usually alternate between collection identifiers (example: publishers, books, users) and resource IDs (example: 123, les-miserables, vhugo1802).

> In Chinese：
> * Resource name 最小单元是 {collection identifier}/{resource ID}。
> * Resource name 可以有多个层级。但应该尽量保持简单。
> * 当 API 使用场景中，resource name 无法保证唯一，就需要多层级的 resource name。例如：
>   * 不同的 publisher 同时出版了名字相同的书 `books/les-miserables`；
>   * 这时，书的 resource name 应设计成 `publishers/123/books/les-miserables`。

* **Clarity and Context**:

  * **Structured Information**: A resource name like "publishers/123/books/les-miserables" provides clear information about the hierarchy and relationships between resources. It immediately tells you that "les-miserables" is a book under the publisher with ID "123".
  * **Context**: Users and developers can understand the context and structure of the resource without needing additional lookups.

* **Disambiguation**:

  * **Unique Within Scope**: While simple IDs can be unique within a single collection, they can become ambiguous when dealing with multiple collections or nested resources. The structured format ensures that resource names are unique across the entire API.

## [Disallow embedding of resources](https://google.aip.dev/122#disallow-embedding-of-resources)

In this example, the `Profile` resource is embedded directly within the `User` resource.

```protobuf
message Profile {
    string profile_id = 1;
    string bio = 2;
    string avatar_url = 3;
}

message User {
    string id = 1;
    string name = 2;
    Profile profile = 3; // Embedded Profile resource
}

```

This design is problematic for a number of reasons, which are as follows:

- If the dependency resource is deleted, what happens to the embedded reference in the dependent resource?
- If every resource has its own set of permissions, a user with read permission on the dependent resource may not have read permission on the dependency resource. This user suddenly cannot see the full resource.
- Changing the requirements in the schema for either resource impacts the other.

Referencing by name is recommended.

In this example, the User resource contains a reference to the Profile resource using its resource name.

```protobuf
message Profile {
    option (google.api.resource) = {
        type: "example.com/Profile"
    };
    string name = 1;
    string bio = 2;
    string avatar_url = 3;
}

message User {
    string name = 2;
    string profile = 3 [(google.api.resource_reference) = {
        type: "example.com/Profile"
    }]; // Reference to Profile resource
}
```

## [Request message of a method that acts on an already-existing resource](https://google.aip.dev/122#fields-representing-resource-names)

When defining a method that retrieves or acts on an already-existing resource (such as `GetBook` or `ArchiveBook`), the first field of the request message **should** be the resource name, which **must** be of type `string` and must be called `name` for the resource name.

The field **should** also be annotated with the `google.api.resource_reference` annotation, referencing the resource type (AIP-123).

```protobuf
// Request message for ArchiveBook
message ArchiveBookRequest {
  // The book to archive.
  // Format: publishers/{publisher}/books/{book}
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "library.googleapis.com/Book"
    }];

  // Other fields...
}
```

## [Request message of a method that creates a new resource or list resources](https://google.aip.dev/122#fields-representing-a-resources-parent)

When defining a method that retrieves resources from a collection or adds a new resource to a collection (such as `ListBooks` or `CreateBook`), the first field of the request message **should** be of type `string` and **should** be called `parent` for the resource name of the collection.

The `parent` field **should** also be annotated with the `google.api.resource_reference` annotation, referencing the parent's resource type (AIP-123).

```protobuf
// Request message for ListBooks.
message ListBooksRequest {
  // The parent to list books from.
  // Format:
  //   - publishers/{publisher_id}
  //   - authors/{author_id}
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "library.googleapis.com/Book"
    }];

  // Other fields...
}
```

## [Extract resource name from HTTP path](https://google.aip.dev/127#http-method-and-path)

The corresponding value represents the URI.

* URIs **must** use the `{foo=bar/*}` syntax to represent a variable that should be populated in the request proto. When extracting a resource name, the variable **must** include the entire resource name, not just the ID component.
* URIs **may** use nested fields for their variable names. (Additionally, AIP-134 mandates this for Update requests.)
* URIs **must** use the `*` character to represent ID components, which matches all URI-safe characters except for `/`. URIs may use `**` as the final segment of a URI if matching `/` is required.

## [Declarative-friendly APIs](https://google.aip.dev/128)

Declarative-friendly resources **should** designate that they follow the declarative-friendly style:

```protobuf
message Book {
  option (google.api.resource) = {
    type: "library.googleapis.com/Book"
    pattern: "publishers/{publisher}/books/{book}"
    style: DECLARATIVE_FRIENDLY
  };

  // Name and other fields...
}

```

If a resource takes time (more than a few seconds) for updates to be realized, the resource **should** include a `bool reconciling` field to disclose that changes are in flight. This field **must** be output only.
