# TiDB Management Service

Please refer to [feishu project development docs](https://pingcap.feishu.cn/wiki/wikcnucEQKNWzQ9uL5farS4qEpH).

<!-- TOC -->
* [TiDB Management Service](#tidb-management-service)
  * [Structure of The Whole Repo](#structure-of-the-whole-repo)
  * [Structure of A Single Module](#structure-of-a-single-module)
    * [`app/`](#app)
    * [`domain/`](#domain)
    * [`infra/`](#infra)
    * [`pkg/`](#pkg)
  * [Development Guide](#development-guide)
  * [Release Process](#release-process)
      * [Considerations](#considerations)
<!-- TOC -->

## Structure of The Whole Repo

- API Definition `./api`

- TiDB Management

  TiDB Mgmt service has two components:

    - TiDB Mgmt Portal `./tidb-mgmt-portal`

    - TiDB Mgmt Service `./tidb-mgmt-service`

- Serverless Management

    - Serverless Global Service `./serverless-global-service`

- Dedicated Management

    - Dedicated Global Service `./dedicated-global-service`

- Temporary Components

    - API Wrapper `./tempo-wrapper`

    - Core-svc Proxy `./tempo-proxy`

    - Migration Tasks `./tempo-migrate`

- Common Utilities `./utilities`

- Functional Test `./functional-test`

- ~~[Deprecated] Infrastructure as Code (IaC) `./deployments`~~

## Structure of A Single Module

![](.github/ddd_overview.jpg)

- `app/`
    - `{app_name}/`
        - `service/`
        - `server.go`
    - `register.go`
- `cmd/`
    - `{cmd_name}/`
        - `main.go`
- `domain/`
    - `svcadapter/`
        - `regionservercli.go`
        - `eventbus.go`
    - `externaladapter/`
        - `jsm.go`
    - `repository/`
        - `cluster.go`
    - `entity/`
        - `cluster.go`
    - `service/`
        - `{service_name}/`
- `infra/`
    - `svcadapterimpl/`
    - `externaladapterimpl/`
    - `repositoryimpl/`
        - `schema/`
            - `cluster.go`
- `pkg/`
    - `apimiddleware/`
        - `auth/`
        - `error/`
        - `header/`
    - `config/`
    - `constant/`
    - `{... other common packages}/`

### `app/`

Business vertical-seperated applications. Each application is a self-contained gRPC-gateway server. It always contains a `service` layer

- `app/{app_name}/server.go` implements the gRPC-gateway server interface.
- `app/register.go` registers all applications to the global gRPC-gateway runtime.

### `domain/`

Core domain model. This package ensures minimal external dependencies.

- `domain/svcadapter/` defines microservice adapter interfaces, such as accountcli, billingcli, eventbus pub/sub, etc.
- `domain/externaladapter/` defines external resources adapter interfaces, such jsm pub (sns).
- `domain/repository/` defines repository interfaces.
- `domain/entity/` defines the domain entities.
- `domain/service/` orchestrates the domain logic between multiple entities.

### `infra/`

Bolsters other layers by implementing abstractions and integrating third-party libraries and systems.

- `infra/svcadapterimpl/` implements microservice adapter interfaces.
- `infra/externaladapterimpl/` implements external resources adapter interfaces.
- `infra/repositoryimpl/` implements the repository interfaces.
- `infra/repositoryimpl/schema/` defines the repository schemas.

### `pkg/`

Common convention for shared code.

- `pkg/apimiddleware/` gRPC request/response middlewares. Such as:
    - Query parameter parsing
    - Error response util
    - Header extract
    - Authorization
    - ...
- `pkg/config/` defines the configuration struct and parses the configuration file.
- `pkg/constant/` defines the constant variables.
- ......

## Development Guide

1. Clone the repository `git clone`
2. Go to the target module directory `cd <module>`.
   > Please read the `Makefile` file under the target module.
3. Modify the code
4. Go mod check, lint, code generation, test, etc.: execute `make`.
5. See check for local runs.: execute `make local-run`.
6. Commit the code and create PR

## Release Process

| Environment | Branch      | Tag         | Trigger                                                                                                                                                    |
|-------------|-------------|-------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Dev         | `main`      | -           | Push **commit** to `main` branch (PR merge)                                                                                                                |
| Staging     | `release-*` | -           | Push **commit** to on `release-*` branch (PR merge)                                                                                                        |
| Prod        | `release-*` | `release-*` | Push `release-*` **tag** on `release-*` branch (GitHub release), need [manually approval](https://github.com/marketplace/actions/manual-workflow-approval) |

#### Considerations

<details>
  <summary>Deprecated Thoughts</summary>

> ~~Currently changing the configurations for staging and prod environments in our Pulumi deployment code is tedious,
mainly due to our branch strategy restrictions where we have to deploy to main first, then staging and finally prod. It
feels quite rigid.~~
>
> ~~I have a proposal here: let's learn from Argo's branch strategy - having only one main branch and tagging staging
and prod on top of main. This reduces the isolation between environments but makes deployment much more flexible.~~
>
> ~~This approach also introduces an implicit requirement of no cherry-picking - code for each environment must satisfy
git fast-forward relationship.~~
>
> ~~Argo CD is quite handy at the Kubernetes layer, as long as someone is dedicated to maintaining the CD
infrastructure (now evolved to Allen's entire team). It has two main disadvantages - deployment manifests are forcibly
coupled with Kubernetes YAMLs, and it relies heavily on a large stack of runtime components to serve it.~~
>
> ~~For our business, the initial requirements were to be able to quickly spin up in any cloud environment and deploy
locally fast. Argo CD would require a lot of foreplay for such needs, while Pulumi or Terraform can execute directly,
better fitting these requirements. Also, Pulumi allows writing in TypeScript, enabling linting.~~

</details>
