Goで始めるGraphQL Federation

この抜粋の内容は次のとおりです。

- Subgraph Server の実装
- Gateway Server の実装
- Subgraph を通す
- Gateway を通す

```mermaid
flowchart LR
    Gateway["Gateway
    Bramble"]
    Subgraph["Subgraph
    gqlgen"]
    Client --> Gateway --> Subgraph
```

さらに詳しく知りたい方は読み続けてください。

---

2023年7月4回目です。

GraphQL Fedetaion についてです。

弊社のモバイルアプリの1つは、ユーザーのネットワーク帯域幅による影響を避けるため、GraphQL を BFF として使っています。

単一ドメイン業務においては、1つの GraghQL で問題ないと思います。
しかし、複数のドメイン業務を扱う場合、各チームは独立して自分たちの GraphQL サービスを開発するため、Supergraph（GraghQL Federation）[^1] にしていく必要があると思います。
[^1]: https://www.apollographql.com/supergraph/

現在弊社の第1言語は、Go です。Go による GraphQL Federation について見ていきます。

## Subgraph Server の実装
- 構成
   - go version go1.20.5 linux/arm64
   - [gqlgen](https://gqlgen.com/) 

https://github.com/99designs/gqlgen

Subgraph[^2] 用の GraphQL Server を立てます。
[^2]: https://www.apollographql.com/docs/federation/v1/subgraphs/

```bash
go install github.com/99designs/gqlgen@latest
gqlgen version
mkdir -p users/
cd users/
go mod init github.com/danny-yamamoto/go-graphql-federation-example/users
go get -u github.com/99designs/gqlgen
gqlgen init
```

Query を仮実装します。

https://github.com/danny-yamamoto/go-graphql-federation-example/blob/0654159a1fb0455f0c81e0d15261e64fc57dc050/users/graph/schema.resolvers.go#L16-L25

https://github.com/danny-yamamoto/go-graphql-federation-example/blob/0654159a1fb0455f0c81e0d15261e64fc57dc050/users/graph/schema.resolvers.go#L43-L64

これで Subgraph 側の準備は完了です。

## Gateway Server の実装
- 構成
   - go version go1.20.5 linux/arm64
   - [Bramble](https://github.com/movio/bramble)

Gateway として、[Bramble](https://movio.github.io/bramble/#/) を使います。

https://movio.github.io/bramble/#/

Bramble の設定に手こずりました。
Subgraph に通すには、`config.json` の定義と `schema.resolvers.go` の実装が必要です。

https://github.com/danny-yamamoto/go-graphql-federation-example/blob/main/cmd/bramble/config.json

Service を足します。

https://github.com/danny-yamamoto/go-graphql-federation-example/blob/7b025a8d1d62a6cfe1dabfee4086b6bcc4563140/users/graph/schema.graphqls#L18-L21

```bash
gqlgen generate
```

generate 後、Service の schema 処理を追記します。

https://github.com/danny-yamamoto/go-graphql-federation-example/blob/7b025a8d1d62a6cfe1dabfee4086b6bcc4563140/users/graph/schema.resolvers.go#L28-L40

これで、両方の実装が完了です。

## Subgraph を通す
さっそく、Subgraph から確認します。

```bash
vscode ➜ /workspaces/go-graphql-federation-example/users (main) $ go run server.go 
2023/07/25 10:10:31 connect to http://localhost:4000/ for GraphQL playground
```

Playground で Query を実行します。
![2023-07-25-a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569971/2d2299da-cadf-9bec-305a-6939fa9339b0.jpeg)

## Gateway を通す
次に、Gateway から Subgraph まで通します。

```bash
vscode ➜ /workspaces/go-graphql-federation-example/cmd/bramble (main) $ go run main.go -conf ./config.json 
{"level":"info","msg":"service was updated","service":"user-service","time":"2023-07-25T10:13:19.655658346Z","version":"0.1.0"}
{"level":"info","msg":"rebuilding merged schema","time":"2023-07-25T10:13:19.655729304Z"}
{"level":"info","msg":"enabled plugins: []","time":"2023-07-25T10:13:19.655875221Z"}
{"config":{"id-field-name":"","gateway-address":"","disable-introspection":false,"metrics-address":"","private-address":"","gateway-port":8082,"metrics-port":9009,"private-port":8083,"services":["http://localhost:4000/query"],"loglevel":"debug","poll-interval":"10s","PollIntervalDuration":10000000000,"max-requests-per-query":50,"max-service-response-size":1048576,"Plugins":null,"Extensions":null,"QueryHTTPClient":null},"level":"debug","msg":"configuration","time":"2023-07-25T10:13:19.655893679Z"}
{"addr":":8082","level":"info","msg":"serving public handler","time":"2023-07-25T10:13:19.656398221Z"}
{"addr":":8083","level":"info","msg":"serving private handler","time":"2023-07-25T10:13:19.656701471Z"}
{"addr":":9009","level":"info","msg":"serving metrics handler","time":"2023-07-25T10:13:19.656738471Z"}
```

```bash
vscode ➜ /workspaces/go-graphql-federation-example (main) $ curl -X POST -H "Content-Type: Application/json" -d '{"query":"{ todos { id text } }"}' http://localhost:8082/query
{"data":{"todos":[{"id":"TODO-1","text":"My Todo 1"},{"id":"TODO-2","text":"My Todo 2"}]}}
vscode ➜ /workspaces/go-graphql-federation-example (main) $ 
```

## Summary
- GraphQL Federation について書きました。
- Gateway として、Bramble を使いました。
- Gateway の起動は、最後である必要があります。deploy 時は、起動順番に気を使う必要があると思います。