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

Feature: @defer support #2395

Open
jpvajda opened this issue Jul 25, 2022 · 21 comments · Fixed by #3093
Open

Feature: @defer support #2395

jpvajda opened this issue Jul 25, 2022 · 21 comments · Fixed by #3093
Assignees
Labels
feature New addition or enhancement to existing solutions

Comments

@jpvajda
Copy link
Contributor

jpvajda commented Jul 25, 2022

One of the disadvantages of GraphQL’s request/response model is that the GraphQL response is not returned to clients until the entire request has finished processing. However, not all requested data may be of equal importance, and in some use cases it may be possible for applications to act on a subset of the requested data. An application can speed up its time-to-interactive if the GraphQL server can send the most important data as soon as it’s ready. The new @defer and @stream directives allow GraphQL servers to do exactly that by returning multiple payloads from a single GraphQL response.

Similar to @stream the @defer directive also allows the client to receive data before the entire result is ready. @stream can be used on list fields. Whereas @defer can be used on used on fragment spreads and inline fragments.

References

https://graphql.org/blog/2020-12-08-improving-latency-with-defer-and-stream-directives/

@jpvajda jpvajda added the feature New addition or enhancement to existing solutions label Jul 25, 2022
@jpvajda jpvajda added this to the Release 2.0 milestone Jul 25, 2022
@Iron-Ham
Copy link
Contributor

I spoke with @calvincestari around getting @defer support in apollo-ios.

There's an ongoing stream of work related to supporting multipart/mixed HTTP requests. To support any kind of incremental transport over HTTP1, this work must be completed first.

Once this work has merged, supporting @defer can come in a variety of flavors. I expect that @defer will have the following impacts:

  1. Impact on code generation. Code generation must be impacted when a selection set is deferred. There are questions about how best to do that. The simplest is perhaps to wrap the selection set in an additional layer of Optional, although I fear that this may not convey what's happening to the end user. For example, if I have linked a Twitter account to my GitHub profile, and I @defer retrieval of that information, the generated property would read something like var twitterProfileUrl: String?? { ... }. That's a bit funky, and perhaps doesn't convey that this field will arrive as a String? based on whether the user does or does not have a Twitter profile linked to their GitHub account. Instead, I propose that we explore the possibility of something like this:
enum ApolloDeferredResponse<T> {
    case loading
    case result(Result<T, Error>)
}

Such that this selection set is now wrapped within this property. I think this may well have some effects down the chain (e.g., is SomeFragment? comparable to ApolloDeferredResponse<SomeFragment>?), but it's certainly an idea worth exploring. I'd say that it's certainly a nice to have that could follow an initial proof of concept implementation with optionals.

  1. Impact on inclusion directives: We should certainly think about and test the ergonomics of using the generated code if it's been generated with @skip and @include directives.
  2. Impact on watchers: My assumption for how defer would work is that the incremental responses would pull the record from the cache (in-memory, SQLite, what have you), update/append it with new data, and save it back to the cache. That will certainly trigger a watcher update. Additionally, for a first implementation, we should return incremental callbacks (including the full record as received from previous parts). For folks using the watcher, this will mean getting the data multiple times. This seems likely fine for a first pass at @defer and can be improved upon in future iterations.

Once the support for multipart/mixed is in place, I'd be happy to begin exploring this in collaboration with y'all.

Footnotes

  1. Incremental Transport over HTTP

@calvincestari
Copy link
Member

Great summary, thanks @Iron-Ham!

@john-twigg-ck
Copy link

@calvincestari @Iron-Ham
Is there a working branch showing the progress?
Cheers for all the work.

@calvincestari
Copy link
Member

Nope, not yet.

@calvincestari
Copy link
Member

For some more context: version 1.2 has taken my focus over the past few weeks and before that another feature that laid some of the groundwork for the incremental delivery protocol. Now with 1.2 released yesterday I can switch back to focus on @defer. The target date for it was mid-May, it is now early to mid-June.

@epitaphmike
Copy link

Does the team have an update on @defer support now that it is GA? Looking forward to being able to test in our iOS and Android apps. Thank you!

@calvincestari
Copy link
Member

calvincestari commented Jun 29, 2023

Does the team have an update on @defer support now that it is GA?

@defer support in Apollo iOS is not GA yet. I'm drafting an RFC and we'll begin the implementation very soon with a release of it by end of July.

@epitaphmike
Copy link

Does the team have an update on @defer support now that it is GA?

@defer support in Apollo iOS is not GA yet. I'm drafting an RFC and we'll begin the implementation very soon with a release of it by end of July.

Gotcha. I was referring to @defer being in GA on ApolloClient, but I guess in the case of the docs that is only for React and not iOS.

Is there anything in the works for Kotlin?

When there is an iOS preview we’d be interested in testing.

Thank you

@calvincestari
Copy link
Member

calvincestari commented Jun 29, 2023

Is there anything in the works for Kotlin?

I believe it's already available for Kotlin, it's just the iOS implementation that is lagging.

When there is an iOS preview we’d be interested in testing

👍🏻

@calvincestari calvincestari linked a pull request Jul 13, 2023 that will close this issue
@calvincestari
Copy link
Member

This is a late update but the RFC is up for review in #3093, and I've started implementation in the feature/defer branch working through the task list in #3093 and creating more as I go.

@fabiengasser
Copy link

Any update on this for iOS?

@calvincestari
Copy link
Member

Any update on this for iOS?

The first preview release was issued a couple weeks ago - https://github.com/apollographql/apollo-ios/releases/tag/preview-defer.1. We're still finishing it off.

@loganblevins
Copy link

How do I disable defer experimental support? I'm on 1.14.0 and the json schema validation is breaking due to defer

@loganblevins
Copy link

Error: JavaScriptError: GraphQLSchemaValidationError-There can be only one directive named "@defer".-GraphQLSchemaValidationError@

@calvincestari
Copy link
Member

@loganblevins - take a look at your schema, how many defer directive definitions are there? If there is more than one it's correctly a validation error.

@loganblevins
Copy link

Screenshot 2024-07-23 at 14 05 29

After running code gen plugin it added this

@loganblevins
Copy link

Our schema line 1 has directive @defer(label: String, if: Boolean! = true) on FRAGMENT_SPREAD | INLINE_FRAGMENT

Why would code gen be creating the duplicate?

@loganblevins
Copy link

🐛 link #3417

@calvincestari
Copy link
Member

@loganblevins - I'll take a look at that issue, thanks.

@calvincestari
Copy link
Member

For context on this issue, I'm leaving it open until the Selection Set Initializer work is complete then we can consider @defer support done.

@loganblevins
Copy link

@calvincestari Thanks for quick reply! Is there a way I can disable this experimental feature in meantime? I couldn't find that key for my config json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New addition or enhancement to existing solutions
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants