LayerX エンジニアブログ

LayerX の エンジニアブログです。

ダウンタイムなしにGraphQLのMutationから引数を削る方法

こんにちは!バクラク事業部の@ysakura_です。バクラクビジネスカードを担当しています。
先日、GraphQLのMutationから引数(InputのField)を削りました。その際、ダウンタイムを発生させない様に複数回に分けてリリースを行いました。GraphQLでのNullの扱いに少し苦労をしたので、その知見を共有出来ればと思います。


この記事は、LayerX Tech Advent Calendar 2022 8日目の記事です。


動作環境

担当するプロダクトでは、GraphQLのライブラリとしてBE(バックエンド)では gqlgen、FE(フロントエンド)では Apollo Client を (React + TypeScript) の構成で用いています。 また、GraphQLのスキーマはバックエンドのレポジトリで管理しています。

サンプルスキーマ

Mutationの引数のInputからFieldを削ります。(参考: Mutations and Input Types)
例えば、下記のGraphQLにおいて UserInput から email を削る事を考えます

input UserInput {
  name: String!
  email: String!
}

type Mutation {
  createUser(input: UserInput!): User
  updateUser(id: ID!, input: UserInput!): User
}

段階的なリリース

下記の順番で、複数回に分けてリリースをしていきます。
基本的には、FEでFieldの送信を止めるスキーマからFieldを削るという流れですが、FEからの送信を止めた段階でエラーとならない様、BEの修正を先に行います。

BE: NullableなFieldに変更する

Non-NullなFieldでは、FEからの送信を止めた段階でBEでエラーが出ます。
※ (エラーの例) "必須なフィールド(email)が存在しません"

そのため、先にNullable(Optional)なFieldに変更します。下記の様に、ビックリマーク(!)を無くせば良いです。

input UserInput {
  name: String!
  email: String
}

Nullableにするので、Nullに対応したコードに修正する必要があります。

BE: Fieldの保存をやめる

最終的にスキーマからFieldを削るので、BEで対象のFieldの保存を止める必要があります。
次のリリースでFEからのFieldの送信を止めるので、BEではNullが入る様になります。
誤作動しない様に、このタイミングでBEでの保存を止めるのが良いでしょう。こちらは前述の変更と同じタイミングでのリリースが可能です。

FE: Fieldの送信を止める

スキーマから対象のFieldを削った状態で、FEからそのFieldを送るとBEでエラーが出ます。
※ (エラーの例) "emailというFieldは存在しません"

そのため、先にFEからの送信を止めます。
今回のApollo Clientのケースでは、 emailを指定しない もしくは undefinedを指定する事で送信を止められます。Nullを指定すると、NullableなFieldゆえ Null が送られてしまうので注意が必要です。ここに気づくのに苦労しました。
参考: GraphQL の引数では「値を入れない」と「null を渡す」を区別できる

BE: スキーマからFieldを削る

最後に、GraphQLのスキーマから対象のFieldを削ります。合わせて、BEでコードの自動生成を行います。
今回の例では UserInput から email を削ります。

input UserInput {
  name: String!
}

type Mutation {
  createUser(input: UserInput!): User
  updateUser(id: ID!, input: UserInput!): User
}

FE: 最新のスキーマを反映する

FEでもスキーマを反映します。
既に、FEでは送らない / BEでは保存しない状態になっているので、このスキーマ反映はBEとFEで順不同です。自分のチームでは既存のデプロイフローに従い、BE → FEの順でデプロイしました。

以上により段階的な移行が実現できます。

まとめ

GraphQLのMutationから引数(InputのField)をダウンタイムなしに削る方法についてご紹介しました。MutationのInputからFieldを削る際には、ケアする事が少し多いです。 この順序を間違えると、FEで保存が出来なくなったり、BEで想定外の値が保存されたりします。また Nullの扱いにも注意が必要です。

明日以降の LayerX Tech Advent Calendar 2022 の記事もお楽しみください!