📚

GraphQLで存在しないエントリーポイントを指定していると誤解した小ネタ

に公開

始めに

小ネタです。

弊社システムではGraphQLを採用していますが、存在しないmutationを指定していると勘違いしたものを残しておきます。

環境

なし。

実装

次のようなクエリがありました。

mutation createUser($input: CreateUserInput!) { 
    createUserWithRole(input: $input) { 
    } 
}

私はcreateUserというサーバのmutationエントリーポイントを実行していると判断していました。しかし、実際にはcreateUserWithRoleを実行しています。このcreateUserはクライアントがどのような実行単位なのかをまとめるためのラベルであり、サーバには関係がありません。ちなみにこのcreateUserのことをoperation名と表現します。

基本的にはクライアントのoperation名とサーバのmutationエントリーポイント名は一致させているコードが多数だったので誤解していました。また、さらに付け加えると私と同じくGraphQLの仕様を正確に知らなかった過去のソースもあり、同じ処理内容なのに別で定義されていたGQLがあったため、混乱を招く結果となりました。

# 呼び出し方が違うだけで中身は同じ。キャッシュされたくないとか、なにか理由があったのかも・・・?
mutation createUser($input: CreateUserInput!) { 
    createUserWithRole(input: $input) { 
    } 
}

mutation createUserWithRole($input: CreateUserInput!) { 
    createUserWithRole(input: $input) { 
    } 
}

本来なら複数のエントリーポイントを実行する処理を一つのoperationとして定義できるので、流用性が高まる良い機能なのですがGraphQLを詳しく知ろうとしなかったので調査にハマる結果となってしまいました。

mutation updateTwoUsers {
user1: updateUser(id: "1", input: { name: "Alice" }) { id name }
user2: updateUser(id: "2", input: { name: "Bob" }) { id name }
}

ソースコード

なし。

終わりに

今回ハマったことにより、GraphQLで一気に複数のエントリーポイントに処理を投げられるということを今回改めて知りました。同じことをREST APIで実行しようとしても、それぞれが独立しているから、RxJSでforkjoin等で処理を集約しなければならないのは結構大変ですね。

GraphQLはどちらかというとフロントに応じた複数リソースの参照のためだけに必要だと認識していたので、更新も一気にできることを知れてよかったです。

とはいえ、ハンドリングが複雑になりそうなので特別なユースケースがない限りはやらないと思います。

Discussion