-
-
Notifications
You must be signed in to change notification settings - Fork 454
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Increase feature-set of the populateExchange for progressive Graphcache adoption #964
Comments
Implementation PlanOnly one data structure is needed to track all fields: interface Field {
activeOperations: number,
parentFields: Set<Field>,
returnTypeName?: string,
fieldName: string,
arguments: any, // NOTE: In the POC we'd just readd them from scratch, YOLO
}
// typename => fieldKey (fieldName + arguments) => Field[]
type Fields = Record<string, Record<string, Field[]>; Fragments won't be tracked anymore. It's assumed that only missing fields from a given selection set are added and that it doesn't matter how they're added, since the API does not care. Case: Mutation that alters Todo,
Case: Reading to Fields with an interface type
|
I'm late to this!
With this point, I think it would be best to always include the full traversed fragment. That in itself is the magic of the populate exchange - by introducing more conditional logic about what we do/don't include, we lose that simplicity and in those cases it's arguably easier then to not use the exchange and just specify the required fields manually. If we do however want to do something like that, making it opt-in might be a way to go # Excuse the bad syntax
mutation SomeMutation(id) @populate(shallow: true)
# `@populate(shallow: true) only includes fields which return primitive types |
After #2897 we have started working towards this however there are a few issues we'll have to solve
And we are missing support for
|
Summary
The
populateExchange
is an effective tool to progressively start using Graphcache more effectively. The current problem with adopting Graphcache is that the user has to at some point make the switch from the Document Cache. The interesting properties of the@populate
directive and Graphcache combined mean however that thepopulateExchange
can be used to progressively use Graphcache like the document cache.In such a scenario the goal would be to allow the
populateExchange
to trigger refetches like the Document Cache does without the user having to write updaters for Graphcache that invalidate entities.Given this mutation to add a
Todo
it may be common to define acacheExchange.updates.Mutation.addTodo
function that adds the newTodo
item to several lists. In this example the mutation returns aTodo
and@populate
adds the appropriate fields.If the mutation also returns a
viewer
field then@populate
may be used on that!This mutation may now update
Query
whichviewer: Query!
links to by adding the appropriate fields.Currently the
populateExchange
does not support field arguments, but if we add those then this use-case is covered! The mutation effectively would be allowed to update any field related toQuery
.In cases where no
viewer
field exists on the schema, we could allow a novel use of the@populate
directive on the mutation operation itself!We could allow the
populateExchange
to send an entirely new query operation in this case which is generated from fields that thepopulateExchange
knows are affected byaddTodo
(i.e. each path fromQuery
toTodo
)Generally it'd be useful for
@populate
to only add affected fields when necessary, meaning when any types under@populate
loop back toQuery
, only fields onQuery
and below should be included until the path reaches the types affected by the mutation. Once these types are reached, the usual@populate
logic applies.Once we allow this, all data may be updated automatically. We can then let the user transition to more Graphcache-based usage by letting them move the
@populate
directive to lower fields.Proposed Changes
@populate
to add and track fields that have arguments, e.g.timestamp(format: UTC)
ortodos(first: 10)
@populate
to be added to the whole mutation operation to "populate" a separate dynamic query to be sent to update all data related to the affected mutation types@populate
fields on anyQuery
(root query type) type to only include paths leading to types affected by the mutation. Once this type is reached the usual populating logic applies, i.e. we include all known fields again.Requirements
I'll lay out more requirements for the third proposed change. This change is crucial to never update all fields on
Query
. If we allow@populate
to add fields for all fields touched by the app onQuery
then eventually it'll fetch all data the app has ever seen, which is a huge amount of data.Instead, we can be smart about filtering, like the following:
Query
(either due to@populate
on the mutation operation which creates a new query, orviewer @populate
which leads to `Query)Todo
.Query
that'll eventually retrieve these types recursively.Todo
), apply the normal populating logic (all fields)Todo
and below by which fields are actually currently in useOpen Problems
There's one problem that we'll need to address first. Given a query for a single todo:
We wouldn't want all
Todo
s to now haveowners
fields. GivenViewer -> populate fields leading to... -> Todo -> populate all fields
we'd do that; all todos would now be queried with theowners
field. So is there a heuristic that also stops these fields from always being populated eagerly?I'd propose, in this case, any field below
Todo
would only receive fields that are currently in use in the app. This way, if schema-awareness is used especially, we'd have all necessary data to render or re-render, but Graphcache can re-send certain queries to get the data again as needed!The text was updated successfully, but these errors were encountered: