Skip to content

Make @defer match the semantics using in Apollo Server #1210

@bbakerman

Description

@bbakerman

The @defer annotation is a useful but no spec compliant extension to graphql.

Today the semantics of how it should act are no specified. The original graphql-java implementation did not put many restrictions in place.

Apollo have added @defer support to their offering an documented its restrictions well.

https://www.apollographql.com/docs/react/features/defer-support.html#defer-usage

@defer can be applied on any FIELD of a Query operation. It also takes an optional argument if, that is a boolean controlling whether it is active, similar to @include.

@include and @Skip take precedence over @defer.

Mutations: Not supported.

Non-Nullable Types: Not allowed and will throw a validation error. This is because deferred fields are returned as null in the initial response. Deferring non-nullable types may also lead to unexpected behavior when errors occur, since errors will propagate up to the nearest nullable parent as per the GraphQL spec. We want to avoid letting errors on deferred fields clobber the initial data that was loaded already.

Nesting: @defer can be nested arbitrarily. For example, we can defer a list type, and defer a field on an object in the list. During execution, we ensure that the patch for a parent field will be sent before its children, even if the child object resolves first. This will simplify the logic for merging patches.

GraphQL fragments: Supported. If there are multiple declarations of a field within the query, all of them have to contain @defer for the field to be deferred. This could happen if we have use a fragment like this:

  fragment StoryDetail on Story {
    id
    text
  }
  query {
    newsFeed {
      stories {
        text @defer
        ...StoryDetail
      }
    }
  }

In this case, text will not be deferred since @defer was not applied in the fragment definition.

A common pattern around fragments is to bind it to a component and reuse them across different parts of your UI. This is why it would be ideal to make sure that the @defer behavior of fields in a fragment is not overridden.

It makes sense for graphql-java to follow suit and put more semantics around how defer can be used.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions