Closed4

[flutter][ferry]mutationのcache updateの挙動を調査

はやぶさはやぶさ

b. 場合によってはUpdateCacheHandlerを使いQueryとResponseを紐づける必要がある

https://ferrygraphql.com/docs/mutations#updating-the-cache

Sometimes we need to update the cache in response to a mutation. Ferry allows arbitrary cache updates following any Operation using UpdateCacheHandler callbacks, which run whenever an OperationResponse is received.

a.に書いた通り、mutationのResponseはキャッシュに保存される。なのになぜUpdateCacheHandlerが必要なのか?
それを理解するためにまずはキャッシュの構造を把握する必要がある。

キャッシュの構造

ferry は hiveをキャッシュとして利用していて、以下のような構造で保存される
Queryをルートにして各データへの参照をIDとして持つ構造になっている。

"Query": {
  "__typename": "Query",
  "me": {
    "$ref": "User:28139dc3-d3ee-4375-85b1-5d53f284f487"
  }
}

"User:28139dc3-d3ee-4375-85b1-5d53f284f487": {
  "__typename": "User",
  "id": "28139dc3-d3ee-4375-85b1-5d53f284f487",
  "firebaseAuthUid": "aaaaaaaaaa"
  "name": "太郎"
},

この構造を踏まえて、ユーザーに関するmutationを考える。

  • ユーザーを更新
    • キャッシュのUserが更新される
    • Queryから辿れる。QueryがUserIdの参照を持っているため。
    • なので基本的にはUpdateCacheHandlerは不要
      • 例外としてクエリ結果のソート順が変わる場合は、UpdateCacheHandlerを呼んでソートし直す必要がある。
  • ユーザーを削除
    • キャッシュから該当のUserが消える
    • Queryから辿れなくなる。QueryからUserIdの参照が消えるため。
    • なのでUpdateCacheHandlerは不要
  • ユーザーを作成
    • 作成したユーザーは保存される
    • Queryからは辿れない。QueryからUserIdの参照を持っていないため。
    • なので作成時は UpdateCacheHandlerという機能を利用し、自分でQueryと作成されたデータを紐づける必要がある。
はやぶさはやぶさ

c. bの別解として、新規作成したデータの親オブジェクトを返すと、UpdateCacheHandlerが不要になる

Userがn個のTagを持っていて、Tagを新規作成する場合を考える。

"Query": {
  "__typename": "Query",
  "me": {
    "$ref": "User:28139dc3-d3ee-4375-85b1-5d53f284f487"
  }
}

"User:28139dc3-d3ee-4375-85b1-5d53f284f487": {
  "__typename": "User",
  "id": "28139dc3-d3ee-4375-85b1-5d53f284f487",
  "firebaseAuthUid": "aaaaaaaaaa"
  "name": "太郎"
  "tags": [
    {  "$ref": "Tag:b2db095a-a04e-4892-bf8a-d05dc5ac6083" },
    {  "$ref": "Tag:5da74e71-0527-446e-a11c-fba680cd4b3e" },
    ]
},
  • Tagを作成するAPIのレスポンスが Tagの場合
    • UpdateCacheHandlerを書いてUserとTagを紐づける必要がある
  • Tagを作成するAPIのレスポンスがUserの場合
    • Userの更新なので、上述の b. に書いたような理由でUpdateCacheHandlerは不要になる。
はやぶさはやぶさ

d. OptimisticResponseのキャッシュまわりをコードリーディングする

https://github.com/gql-dart/ferry/blob/636d5756ca/packages/ferry_cache/lib/src/cache.dart#L192-L196

/// Normalizes [data] for the given fragment and writes it to the [Store].
///
/// If an [optimisticRequest] is provided, the changes will be written as an
/// optimistic patch and will be reverted once a non-optimistic response is
/// received for the [optimisticRequest].

OptimisticResponseの場合、キャッシュはDB(hive)に書き込まれず、オンメモリ上のMap に書きこまれる。
non-optimisticなresponseがくるとpatchは消える。
これは UpdateCacheHandlerからキャッシュに書き込んだ場合も同様である。

このスクラップは2022/02/23にクローズされました