1.12時代に書いたメモなので2019-12-06現在最新ver(1.13)の状態には合わないかもしれないけど一応忘備録として公開しておく
このメモに書いた内容はGitHubにboilerplateとしてまとめてある
ここで挙げられたライブラリの基本的な選定の基準としては一つのライブラリであまり多くのことをやろうとせずUNIX哲学的にシンプルに一つの責務のみをこなし他ライブラリとのinteroperationがしやすいものを選ぶという感じ
GoでGraphQLサーバを実装する上で必要になりそうなチェックリストとその対策
- GraphQL
- ORM
- 認証
- 認可
- ルーティング
- DB
- バリデーション
- セキュリティ (CSRF)
- マイグレーション
- ロギング
- テスト (E2E, Unit)
- ドキュメンテーション
- ページング
- モジュール化
- Fixture
- キューイング
- ホットリロード
- i18n
- パッケージング
- デプロイ
環境
- go 1.12
- gqlgen
- chi
Router
Chiを使う
gqlgen公式でサンプルとして紹介されているが標準インターフェースのhttpパッケージでやり取りしてるので相互運用性がよい
GraphQL
gqlgenを使う
そのまま使うとN+1クエリが出てしまうのでdataloadenでクエリをまとめる。仕組みとしてはdataloadenが1msほどwaitしてクエリをまとめてN+1クエリをIN句を使ったクエリに変換している
ORM
sqlboilerを使う
認証
JWTで行う
chiのmiddlewareのjwt-authを使う
今回はトークンのRevokeは要件にないので一旦は問題なし
認可
JWTは本人性の確認のみなので認可は別途実装する必要がある
おおざっぱな認可はGqlgenのdirectiveを使う
詳細な認可はcasbinでRBACで認可を行う
@hasRole(role: ADMIN)
問題: 管理画面系のクエリ、Mutationはどうするか
/query
という同一のエンドポイントで管理画面用のクエリを別に用意する?
クエリ一覧がわかりづらくならないか
type Query {
hero(id: Int): Hero
droid(id: Int): Droid
}
ルーティング
GraphQLなので基本的には必要ないが一部分APIにしたいというような場合はchiのルーティングを使う
DB
ORMはsqlboilerを使う
バリデーション
GraphQLの型チェックはする
+カスタムのバリデータとしてozzo-validationなど使う
出来れば宣言的にバリデーションしたいがsql-boilerが動的にタグを生成していじってはいけないのでタグに埋め込む形のバリデータと少し相性が悪い
各modelのStructにValidateメソッドを生やしてその中で各フィールドのバリデーション、任意のタイミングでValidateメソッドを実行
セキュリティ
chiのmiddlewareを使う
migration
sql-migrateを使う
→ packr でのマイグレーションファイルのマウントに対応してたので
これによりシングルバイナリでサーバにポン置きでmigrationを実行出来る
ロギング
logrusでJSON形式で出力
テスト (E2E)
unitはtestify
graphqlクライアントとしてgo-graphqlでリクエストする
E2Eはdreddなど別途ツールを使ってもいいかも
ドキュメンテーション
GraphQLのIntrospectionで提供
開発サーバにplaygroundを埋め込み
本番環境では無効にする
ページング
Cursor-based pagination
モジュール化
go 1.11より導入された Go module で管理
Fixture
事前に作成したSQLを直接読み込ませるか
https://github.com/zhulongcheng/testsql
gp-sqlmockで仮想的にmockデータを作りそれでやりとりさせるか
キューイング
外部にキューイング用のバックエンドを用意する想定
redisをバックエンドにmachineryを使う
ホットリロード
2019-03-21現在 Go 1.12のGo Modulesに対応していなかったのでgo.modファイルを使う場合は多少設定ファイルをいじる必要がある
i18n
go-i18nで多言語化対応
パッケージング
packrを使いマイグレーションファイルなどの静的ファイルをバイナリにembedする
デプロイ
packrでシングルバイナリにしたあとalpineイメージにビルド後のバイナリをADDしてデプロイ用のイメージ作成
scratchでもいいけどなんだかんだでコンテナ内でapkコマンド叩けると嬉しい場面が多いのでそこまでシビアにイメージサイズ絞りたいとかでなければalpineで問題ないと思う