Skip to content
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

[WIP] Add client side support for @defer directive #3686

Closed
wants to merge 49 commits into from

Conversation

clarencenpy
Copy link
Contributor

@clarencenpy clarencenpy commented Jul 13, 2018

Changes:

  • Merge deferred patches with the initial response and write to cache
  • Merge deferred errors into queryStore
  • Expose field-level loading states for deferred queries in loadingState
  • New networkStatus for deferred queries that are still streaming

This depends on an alpha release of apollo-link-dedup #714.

@clarencenpy clarencenpy force-pushed the defer-support branch 2 times, most recently from f92550b to 1c08016 Compare July 17, 2018 19:40
@clarencenpy clarencenpy changed the title [WIP] Add client side support for @defer directive Add client side support for @defer directive Jul 18, 2018
@apollographql apollographql deleted a comment from apollo-cla Jul 18, 2018
@apollographql apollographql deleted a comment from apollo-cla Jul 19, 2018
@apollographql apollographql deleted a comment from apollo-cla Jul 19, 2018
Copy link
Member

@hwillson hwillson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking AMAZING @clarencenpy! See my comments inline (nothing major). Thanks!

// If loadingState is present, this is a patch from a deferred
// query, and we should always treat it as a different result
// even though the actual data might be the same (i.e. the patch's
// data could be null.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing closing ")" in comment.

* Recursive function that extracts a tree that mirrors the shape of the query,
* adding _loading property to fields which are deferred.
*/
function extractDeferredFieldsToTree(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding extractDeferredFieldsToTree and initDeferredFieldLoadingStates, I see they're defined as utility functions outside of the QueryManager class. I don't really have any issues with this, but since the rest of the QueryManager functionality is already defined in the class, would you mind moving these into QueryManager as private functions?

* Only a partial response has been received, this could come from the usage
* of @defer/live/stream directives.
*/
partial = 9,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is sooooo exciting! 🎉

@@ -52,5 +58,5 @@ export enum NetworkStatus {
export function isNetworkRequestInFlight(
networkStatus: NetworkStatus,
): boolean {
return networkStatus < 7;
return networkStatus < 7 || networkStatus === 9;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to pose a bit of an interesting problem. I've seen a lot of 3rd party code that is using the networkStatus < 7 check to see if a request is in flight. It's too bad the NetworkStatus enum wasn't originally defined using increments of 10, so the partial status could have been added just after poll (so poll at 60, partial at 61). That being said, progress is progress - there isn't much we can do here for now, so 👍.


/**
* Define a new type for patches that are sent as a result of using defer.
* Its is basically the same as ExecutionResult, except that it has a "path"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small grammar issue - should be "It is".

* field that keeps track of the where the patch is to be merged with the
* original result.
*/
export interface ExecutionPatchResult {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like ExecutionPatchResult is very similar to ExecutionResult (just adds path). You might be able to extend the ExecutionResult interface instead?

@@ -11,6 +13,8 @@ export type QueryStoreValue = {
networkStatus: NetworkStatus;
networkError?: Error | null;
graphQLErrors?: GraphQLError[];
_loadingState?: Record<string, any>;
loadingState?: Record<string, any>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we avoid the underscore naming here - seeing both _loadingState and loadingState is a bit confusing. Maybe _loadingState should be called something like originalLoadingState?

* The structure of this will mirror the response data, with deferred fields
* set to undefined until its patch is received.
*/
function compactLoadingStateTree(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as earlier - would you mind moving this into the QueryStore class, as a private function?

patch: ExecutionPatchResult,
): void {
if (patch.errors) {
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming this is because these changes are in alpha state, but just calling this out as a reminder. Something needs to be done with patch.errors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic to do that is in queries.ts, where I merge errors for each patch into the graphQLErrors array. My bad, forgot to take this out.

@apollographql apollographql deleted a comment from apollo-cla Jul 20, 2018
dandv and others added 18 commits July 23, 2018 06:40
The existing page for "Add React to a New App" (previously; now broken: https://reactjs.org/docs/add-react-to-a-new-app.html) has been moved to https://reactjs.org/docs/create-a-new-react-app.html.

This updates the documentation to accommodate that change!
The motivation behind this is the need to distinguish between
"pending" or "null" states for deferred fields.
This allows us to omit `children` from the access path.
Even though the actual data might look the same (i.e. the patched data
is null)
@defer must be specified for all of the selections, matching up with
the behavior of Apollo Server.
 - apollo-boost@0.2.0-alpha.0
 - apollo-cache-inmemory@1.2.6-alpha.0
 - apollo-cache@1.1.13-alpha.0
 - apollo-client@2.4.0-alpha.0
 - apollo-utilities@1.0.17-alpha.0
 - graphql-anywhere@4.1.15-alpha.0
# Conflicts:
#	docs/source/features/defer-support.md
#	packages/apollo-client/package.json
#	packages/apollo-client/src/core/QueryManager.ts
 - apollo-boost@0.2.0-alpha.14
 - apollo-cache-inmemory@1.2.6-alpha.14
 - apollo-cache@1.1.13-alpha.14
 - apollo-client@2.4.0-alpha.14
 - apollo-utilities@1.0.17-alpha.14
 - graphql-anywhere@4.1.15-alpha.14
@apollographql apollographql deleted a comment from apollo-cla Aug 8, 2018
@apollo-cla
Copy link

Warnings
⚠️

❗ Big PR

⚠️

There are library changes, but not tests. That's OK as long as you're refactoring existing code

Generated by 🚫 dangerJS

@hwillson hwillson changed the title Add client side support for @defer directive [WIP] Add client side support for @defer directive Aug 12, 2018
@rmosolgo
Copy link

rmosolgo commented Mar 5, 2019

👋 Hi! Is this something that you all are still working on? I'd love to use @defer but I've been having some trouble with the last releases of it. Could I help by getting it up-to-date with the new 2.5 release?

@Yalian
Copy link

Yalian commented Jul 30, 2019

some update for this feature? 🤓

@sorenhoyer
Copy link

Defer will add so much value... Anyone working on this? 1 year later... what's blocking this? :-)

@hwillson
Copy link
Member

hwillson commented Sep 4, 2019

Fully integrated production @defer support is coming in the not too distant future, but it won't be part of Apollo Client 3.0. Both Apollo Client and Apollo Server are undergoing major infrastructure and functionality changes for their 3.0 releases, a lot of which is intended to lay a better foundation for @defer and @stream support. When AC/AS are ready, the great work done in the PR will be reviewed and adjusted as needed, to get first class @defer support in place. Closing for now - thanks!

@hwillson hwillson closed this Sep 4, 2019
@lukejagodzinski
Copy link

@hwillson Any rough approximation of the featuring landing? 2019 or 2020?

@hwillson
Copy link
Member

@lukejagodzinski I think it's safe to say 2020 as this point. @defer and @stream support is coming, but it has been back-burnered a bit.

@lukejagodzinski
Copy link

@hwillson thanks, but early 2020, mid, or late? :D

It's also a little bit misleading to watch some videos about @defer on YT, see it in some places in docs, read article about it from 2018 and still not being able to test even experimental version :). I'm just saying, that after seeing so many old news about that, I assumed that this feature was already implemented. Until I digged deeper :). Maybe, it could be mentioned in the docs that this feature is still WIP? Just create a new section in docs, so anyone who will encounter news about @defer and go to the docs, will see that it's not implemented yet :)

@hwillson
Copy link
Member

Thanks @lukejagodzinski - great point. We had a defer section in the docs, but we removed it when work on @defer stopped (so we weren't misleading people with regards to how complete the feature was). We'll look into getting a note about @defer back in the docs. Regarding when it will be ready in 2020, that's a great question. To be honest that decision is dependent on when @defer support is ready in Apollo Server, and Apollo Server is undergoing a lot of great changes for v3. We'll be diving back into @defer after AS 3 launches, as some of the v3 changes are required to build a proper @defer / @stream experience.

As for when AS 3 is launching, I just asked the server team and they told me ... 2020 🙂.

For more specific details around AS 3 and @defer support, I'd suggest joining in the roadmap discussion.

@lukejagodzinski
Copy link

@hwillson ok thanks! :) Can't wait for it :) Keep doing great work!

@fabis94
Copy link

fabis94 commented Dec 10, 2020

Any updates here? Looks like there hasn't been any activity for a year neither here nor in the Apollo Server repo

@KatFishSnake
Copy link

@fabis94 i hope that graphql/graphql-js#2839 is the next step for this PR

@hwillson
Copy link
Member

@KatFishSnake this work is now being tracked in #8184, and will be part of Apollo Client 4.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 1, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet