よこやまの日記・ブログを自作する編

車輪の再開発でも自分専用ブログをつくるんや!

19日目: 勢いでN+1問題対応入れたけど今は不要だった

初めてのGraphQL ―Webサービスを作って学ぶ新世代API

初めてのGraphQL ―Webサービスを作って学ぶ新世代API

GraphQLの怖いところN+1

前回は一つのクエリが重くなることに対する負荷対策を入れた。(実際問題としてできているかは微妙だけど)

今回は、GraphQLで陥りがちなデータベースアクセスのN+1問題について対策する。 N+1問題は、配列の要素で入れ子になった項目を再帰的に取得しにいってしまうためにデータベースに高頻度のアクセスが発生してしまう問題。

これについても対策する機能は用意されている。それがこちら。

github.com

コレを使うことで、都度DBアクセスをするのでなく、ある程度まとめて取得しに行くことを実現できる。 で、早速導入をしてみたんだけど、結果的には現時点ではあまり効力を発揮しなさそう。どちらかというと前後の記事を取得するところで必要そうだけど、あちらはちょっと複雑なクエリなので導入を見送り。

導入の仕方

防備録としてもメモしておく。

N+1対策したい対象に対して以下のようにDataLoaderの生成を定義する。もともと配列を返す箇所についてはこちらも同様に配列をしている。intはIDがint型であるため。IDが文字列型ならstringを指定。

//go:generate go run github.com/vektah/dataloaden ArticleLoader int *github.com/hiroyky/legato/domain/dbmodel.Article
//go:generate go run github.com/vektah/dataloaden ArticleSliceLoader int []*github.com/hiroyky/legato/domain/dbmodel.Article

生成

$ go generate ./
$ go generate ./...

生成されたDataLoaderを使って呼び出しを行う。

詳細は本日のプルリクで。

github.com

18日目:重いGraphQLのクエリを制限する機構を導入

初めてのGraphQL ―Webサービスを作って学ぶ新世代API

初めてのGraphQL ―Webサービスを作って学ぶ新世代API

GraphQLの1クエリは重くできる

GraphQL APIってREST APIと違ってクライント側の裁量が大きいAPIである。REST APIはサーバ側がレスポンス内容を指定するのに対して、GraphQLはクライント側が内容を指定するから。そして、一つのクエリをとても重くすこともできてしまう。

クエリはたとえ1つでもデータベースのあらゆる関連テーブルを走査して、大きな負担をかけてしまう可能性も十分ありえる。

そこで今回は、重いGraphQLクエリを制限する機能を付ける。

Complexity

使っているGraphQLライブラリgqlgenはありがたいことにクエリの重さを算出して、合計値が閾値以上だったらリクエストをキャンセルする機能を持っている。公式では以下のように解説されている。

gqlgen.com

各種項目について“重さ”を計算させる関数を指定して、その合計値でクエリの重さを比較する感じ。

プルリク

というわけで本日のプルリク。まぁいったんはViewer向けのみで良いでしょw

github.com

github.com

17日目:日付順でソート

開発で期間が空くとこのブログが自分が何をやってきたかが分かる良い機会になる。 プルリクをマージしてから大分期間が空いたけど、ここに書いておくと開発の間に時間が経っても振り返りやすくなるので書いておく。

今まで記事の順番はテキトーでMySQLのインクリメント順とかだった。それだと当然ながら意味ないので日付順にソートできるようAPI,フロント両方を改修した。APIは他のソート順も対応すべきだけど、いったんここまで。

github.com

github.com

15日目:前後の記事を取得できるようにGraphQLを拡張する

前後の記事に遷移するために

前回は、既存のGraphQLに対してApollo Clientで記事をざっくり表示する部分を作成しました。続いてページネーションで前後の記事に遷移できるリンクを作ろうとしました。

が、そんなスキーマ定義はしていなかったので改修しました。

そのプルリクがこちら。 このように外部参照がある場合、スキーマ定義の型と実施のコード上の型が異なるため、gqlgenの設定ファイルでコード上の型を指定するところがポイント。

github.com

14日目: Apollo GraphQL Client(vue用)で記事の読み込み

GraphQLのクライアントの作成

GraphQLのクライアントをどうしようかと思ったけど、まずはオーソドックスにApollo Clientを利用することにした。そしてこのVue向けであるこちらを導入。

github.com

概ねTypeSciriptにも対応しているようで一安心。 Vueファイルに直接クエリを指定するわけなんだね。

通信部分と表示部分のコードを厳密に分けるのが好みなので、ちょっと違和感あるけどまずはこのまま進める。 毎回画面表示時には必要な項目はサーバからGraphQLで読み込むようにして、Store(vuex)は無しにした方が良いかなぁ。あんまりフロントエンドで状態を持つべきじゃ無いかも、今回は。

というわけで、今日のプルリク。今後もVue apolloを導入するときの参考にしよう。

github.com

13日目: Buefy導入

表示をようやく作る、少しだけ。

前回AWS LambdaでNuxtをサーバサイドレンダリングで動かすということをやった。で、ついでにLambda上でソレを実現するためのQiita記事も書いた。

qiita.com

さて、今回は実際に中身の実装をしていく。

最初、フロントエンドのUIフレームワークはVuetifyにするつもりであったが、Vuetifyだと業務感が出てしまうので辞めることにした。もちろんVuetifyはとても良いフレームワークで何度かお世話になった。

今回は、BuefyというBulmaをVue向けにラッパしたものを使うことにした。

今日のプルリクは以下。

github.com