SpaceCloudでMySQL/GraphQLサーバを立ち上げる

## 本記事で触れないこと
- GraphQLに関する解説
- Rest APIとの比較に関して  
※ `RestAPI GraphQL 比較`等のキーワードでggると、参考になる記事がヒットすると思います

## Space Cloudについて
- フロントエンドから`GraphQL`(または`REST API`)を呼び出すためのAPIサーバ
- MySQL + GraphQLサーバを立ち上げる場合の有力候補  
※ [prisma](https://github.com/prisma/prisma)もかなり有名（比較/検証予定）  
※ Postgressの場合は[hasura/graphql-engine](https://github.com/hasura/graphql-engine)が人気みたい
- Goで書かれており、クラウドネイティブのルールに従って水平方向にスケーリングしてくれるらしい

### 対応DB
- MongoDB
- PostgreSQL、およびPostgreSQL互換のデータベース（CockroachDB、Yugabyteなど）
- MySQLおよびMySQL互換データベース（TiDB、MariaDBなど）

## 事前準備
### Docker環境の用意
- 公式の[Quick start](https://github.com/spaceuptech/space-cloud#quick-start)に従い、docker-composeで構築します
- MySQL5.7バージョンを明示的に指定 ＋ my.cnfの設定を上書き ＋ DBデータの永続化を設定しています

```yaml:docker-compose.yaml
version: "3.7"
services:
  space-cloud:
    image: spaceuptech/space-cloud
    ports:
      - "4122:4122"
      - "4126:4126"
    links:
      - testdb
    restart: always
    environment:
      ## The DEV environment lets you skip login in Mission Control
      DEV: "true"
      ## Change the login credentials of Mission Control (Admin UI)
      # ADMIN_USER: "admin"
      # ADMIN_PASS: "123"
      # ADMIN_SECRET: "some-secret" # This is the JWT secret used for login authentication in Mission Control
  testdb:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: testdb
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
      - ./testdb/data:/var/lib/mysql
      - ./testdb/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./testdb/sql:/docker-entrypoint-initdb.d
    ports:
      - 3306:3306
```

```cnf:mysql/my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

[client]
default-character-set=utf8mb4
```

### DBスキーマの作成
以下の要領でMySQLのスキーマを作成しておく
（docker-composeで作成したMySQLコンテナにログイン + MySQLに接続 + スキーマ作成)

```bash
$ docker-compose exec testdb bash

root@04ee656af514:/# mysql -u root -p root

mysql> create database testdb;
Query OK, 1 row affected (0.01 sec)

mysql> exit
```

## Space Cloud操作
### プロジェクト作成
任意のプロジェクト名を入力し、MSQLの項目を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165108/a5cf0832-364c-540b-81a5-72dc93df01be.png)
※ キャプチャを撮り忘れたので[こちら](https://medium.com/spaceuptech/instant-graphql-apis-on-mysql-d2457e1c177d)から転載しています
（実際の操作では`MYSQL`を選択しています)
### DB接続設定
メニューの`Database`から`Edit Connection`を選択し、ダイアログ内に`root:root@tcp(testdb:3306)/`を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165108/e196227f-3568-5d58-fc6d-f6ce5b27d61f.png)
※ こちらもキャプチャを忘れたので、先ほどと同じく転載画像です

### テーブル作成
`Add a table`ボタンから、任意のテーブル名＋テーブル定義を記載する
![スクリーンショット 2019-11-25 16.19.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165108/d53286a9-9d4e-db1c-8c0e-07dc7819722d.png)

#### create users table
```
type users {
  id: ID! @primary
  phone: String!
}
```

#### create post table
後のselect joinクエリのサンプルで利用したいので、もう一つテーブルを作っておく
先ほど作成したusersテーブルを「外部キー参照」したい場合は、以下のように`@relation`ディレクティブを指定する

```
type post {
  id: ID! @primary
  title: String!
  users_id: users @relation
}
```


### クエリ発行
メニューの`Explorer`から直接クエリの実行が可能
![スクリーンショット 2019-11-25 16.27.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165108/9d3c012f-fa17-0c34-fa08-f67c50525c6f.png)

#### INSERT
```graphql
mutation {
 insert_users(
   docs: [
    { id: "1", phone: "09011112222"},
    { id: "2", phone: "09033334444"}
  ]
 ) @mysql {
   status
 }
}
```

```graphql
mutation {
 insert_post(
    docs: [
      { id: "1", users_id: "1", title: "test_title1" },
      { id: "2", users_id: "1", title: "test_title2" },
      { id: "3", users_id: "2", title: "test_title3" },
      { id: "4", users_id: "2", title: "test_title4" }
    ]
 ) @mysql {
   status
 }
}
```

#### SELECT

##### 単一テーブルのSELECT
```graphql
query {
 users (
   where: {id: "1"}
 ) @mysql {
   id
   phone
 }
}
```

##### 複数テーブルのJOINクエリのサンプル
```graphql
query {
 users @mysql {
   id
   phone
   post(
     where: {users_id: "users.id"}
   ) @mysql {
     title
   }
 }
}
```

#### UPDATE
```graphql
mutation {
 update_users (
   where: { id: "2"},
   set: {phone: "08077778888"}
 ) @mysql {
   status
 }
}
```

## 課題

クエリで日本語等のマルチバイト文字を送信した際に、`Network error: Failed to fetch`のエラーが出てしまったので、`mysql/my.cnf`で文字コードの設定などチューニングの必要がありそう

## 参考
- [spaceuptech/space-cloud](https://github.com/spaceuptech/space-cloud)
- [Instant GraphQL APIs on MySQL - SpaceUpTech - Medium](https://medium.com/spaceuptech/instant-graphql-apis-on-mysql-d2457e1c177d)