Description
Summary
Hi, at Lifeworks we are watching queries in parts of the app. After upgrading to Apollo 1.2.1 we started observing failures when watching a query when a nullable type is null, leading to constant re-fetches of this query.
We ran a quick investigation and this is the result:
- Watch is done using
GraphQLQueryWatcher.store
GraphQLSelectionSetMapper
is called with default initializer which assumes (handleMissingValues: HandleMissingValues = .disallow
) in the accumulator parameter oftransaction.readObject
- which disallows null values for a field- Because
handleMissingValues
isdisallow
,GraphQLSelectionSetMapper.acceptMissingValue
throwsJSONDecodingError.missingValue
- Error is passed to ApolloStore.withinReadTransaction
(lldb) po error
▿ GraphQLExecutionError
▿ path : some.field.on.schema.11.nullableFieldItself
▿ head : Optional<Node>
▿ some : <Node: 0x600001f0f600>
- underlying : ApolloAPI.JSONDecodingError.missingValue
GraphQLQueryWatcher.store
failure condition triggers a re-fetch on failure, cycle repeats
We observed that contrary to load, the values are stored with allowForOptionalFields
, if that is of any help.
To summarize:
- cache shouldn’t fail when null if is nullable
- the watcher probably shouldn't do a remote refresh on an error
- insert/updates on the cache should fail if wrong data is being inserted (fail early, not let us insert and then fail when retrieving)
Version
1.2.1
Steps to reproduce the behavior
- Use a query which contains a nullable type
- Watch the query
- Backend should respond with the value being null
- When written to and loaded from the cache, an error will be thrown and will result in a remote refetch
Logs
(lldb) po error
▿ GraphQLExecutionError
▿ path : some.field.on.schema.11.nullableFieldItself
▿ head : Optional<Node>
▿ some : <Node: 0x600001f0f600>
- underlying : ApolloAPI.JSONDecodingError.missingValue
### Anything else?
_No response_
Activity