Slide 1

Slide 1 text

async_graphqlのguardが便利だった話 2022/5/22 Rust、何もわからない….vol8 hige_yy @kia5n_y2_mud

Slide 2

Slide 2 text

higeです。 • 本名は山中です • 202012~ estie • 元々はフロントエンド領域 • オーディオオタク • ビアポンなるパーティゲームの元日本代表 1

Slide 3

Slide 3 text

2 1. async_graphqlを使ってGraphQL移行した話 2. 便利だったものの話 3. 大変だったことの話 4. まとめ こういう話しますよ

Slide 4

Slide 4 text

GraphQLに移行するぞ!!!

Slide 5

Slide 5 text

4 1. 現状はReact + Rust(REST)の構成だが、ユースケースごとにフロントでリソースの結合 成形を行っている箇所が複数あってちょっとつらい 2. 見た目のちょっとした変更のためにバックエンドまで変更しなければならないことが 多々ある 3. フィールド単位で参照の権限を設定したいが、似たような実装が毎回必要になる 4. ……etc なぜGraphQLにしたいか 移行したいので検証を実施した - Juniperで試しに実装してみる話 (Rust何もわからないvol.4) - 結果、やりたいことはできそう。

Slide 6

Slide 6 text

5 Juniper or async_graphqlで検討 差分は大きくなかったが以下が決め手になりasync_graphqlを使うことに - OneofObjectが使える - Inputで値が入ったEnumが使える - Fieldの定義とGuardが柔軟に行えそう - Fieldごとに設定可能でResolver実行前に実行されるもの 技術選定の話

Slide 7

Slide 7 text

6 - crateをいくつかにわけて開発 - api - sql - usecase - middleware - ……etc 元々どんな感じで作っていたか

Slide 8

Slide 8 text

7 - crateをいくつかにわけて開発 - api <- ここを部分的にgqlに移行 - sql - usecase - middleware - ……etc どんな感じで移行するか

Slide 9

Slide 9 text

8 ざっくりと実装はこんなイメージ

Slide 10

Slide 10 text

9 移行していく 開発チームを一時的に機能開発組と移行組に分割して実施 移行できて嬉しいものから移行していった 結果、1週間と少しで主要な参照が移行完了。 以降、作成されるAPIはgqlになり順次作成・更新系を移行中。

Slide 11

Slide 11 text

10 運用に移って GraphQLにチーム全員が慣れているわけではないので、ちょくちょくつま づきは起きていますが、おおむね問題なく運用できています。 当初困っていたフロントエンドが複雑になる部分は無事解消されました。

Slide 12

Slide 12 text

便利だったものの話

Slide 13

Slide 13 text

12 FieldGuard こう定義して こうやって使う

Slide 14

Slide 14 text

13 なぜ便利だったかの話 不動産ドメインには多くの登場人物が存在します - ビルを保有する人 - ビルを管理する人 - 募集を出す人 - 営業をする人 - 部屋を借りたい人 - ……etc 同じ“ビル”を指していても全く同じ情報が全てのユーザに見えて良いわけで はありません。

Slide 15

Slide 15 text

14 なぜ便利だったかの話 ここでは簡単のために以下のユーザが存在していると仮定します - ビルの貸主 - 他社のビルは閲覧できない - テナント - 全てのビルを閲覧できるが見えない項目がある - 管理者 - 全て閲覧可能

Slide 16

Slide 16 text

15 なぜ便利だったかの話 このようなビルを考える

Slide 17

Slide 17 text

16 なぜ便利だったかの話 RESTでやっていた時…… -> 全部分けて定義する? -> Optionalな型にして返す?

Slide 18

Slide 18 text

17 なぜ便利だったかの話 見ても良い条件を満たさない場合Errを返すGuardをユーザごとに作成

Slide 19

Slide 19 text

18 なぜ便利だったかの話 このように表現可能になります。

Slide 20

Slide 20 text

19 なぜ便利だったかの話 1. 一見してどのフィールドが誰に公開されているのかわかる 2. 同一のロジックで処理が可能 3. ctxと引数を受けることができるので柔軟なGuardの記述が可能

Slide 21

Slide 21 text

20 Remote Enum レイヤーを跨ぐ構造体について依存を切るために詰め替えたりしますよね。 でも何度も impl From<~> ……するの結構大変ですよね。 特にenumのこれ

Slide 22

Slide 22 text

21 Remote Enum remote-enumを使うと実に楽になります。

Slide 23

Slide 23 text

22 できないこともある 値のあるEnumについては使えません。

Slide 24

Slide 24 text

23 値のあるEnumについてはどうするか パターン1: Unionを使う 全て値を持っている場合、Unionが使えます。 パターン2: 型を一部諦める 今のところこれは良い!という手段は特になし。

Slide 25

Slide 25 text

大変だったことの話

Slide 26

Slide 26 text

25 複雑なSQL操作でAcquireを使うと lifetime error になる これ

Slide 27

Slide 27 text

26 どういう時に起きるか acquireを要求している関数を複数呼んでいる関数があり

Slide 28

Slide 28 text

27 どういう時に起きるか それをLoaderで呼び出した場合に起きます

Slide 29

Slide 29 text

28 どうやって解決したか Acquireを要求していた箇所を MySqlConnectionに変更するととりあ えずCompileは通るようになります。 何がだめなのか……?

Slide 30

Slide 30 text

29 ちょっと調べてみた cargo-expandを使って 該当箇所をexpandすると……

Slide 31

Slide 31 text

30 ちょっと調べてみた 一部コメントアウトすると通る

Slide 32

Slide 32 text

31 ちょっと調べてみた どうやらnotesを引いてるところで こけてるみたい…… 結論わかんない ということがわかりました!

Slide 33

Slide 33 text

まとめ

Slide 34

Slide 34 text

33 まとめ 1. async_graphqlのGuardは便利だった。 2. LifetimeのErrorは難しい。sqlxを使うなら気をつけよう。

Slide 35

Slide 35 text

34 追記 折角なので、sqlx + async_graphqlの環境を作っておきました。 async_graphqlに興味が出た方はいじってみてください。 (あとあのErrorがわかる方の解説もお待ちしてます) https://github.com/savacan/rust-gql-sample

Slide 36

Slide 36 text

35 estie(エスティ) は オフィス不動産を デジタル化する会社です