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

feat(GraphQL): Extend Support For Apollo Federation #7275

Merged
merged 16 commits into from
Jan 28, 2021

Conversation

minhaj-shakeel
Copy link
Contributor

@minhaj-shakeel minhaj-shakeel commented Jan 12, 2021

Fixes GRAPHQL-917.

This PR extends support for the Apollo Federation.

Support for Apollo federation directives

Our current implementation allows support for 3 directives, namely @key, @extends and @external.

@key directive.

This directive is used on any type and it takes one field argument inside it which is called @key field. There are some limitations on how to use @key directives.

  • User can define @key directive only once for a type, Support for multiple key types is not provided yet.
  • Since the @key field act as a foreign key to resolve entities from the service where it is extended, the field provided as an argument inside @key directive should be of ID type or having @id directive on it. For example:-
type User @key(fields: "id") {
   id: ID!
  name: String
}

@extends directive.

@extends directive is provided to give support for extended definitions. Suppose the above defined User type is defined in some service. Users can extend it to our GraphQL service by using this keyword.

type User @key(fields: "id") @extends{
   id: ID! @external
  products: [Product]
}

@external directive.

@external directive means that the given field is not stored on this service. It is stored in some other service. This keyword can only be used on extended type definitions. Like it is used above on the id field.

Generated Queries and mutations

In this section, we will mention what all the queries and mutations will be available to individual service and to the apollo gateway. We will take the given schema as our example:-

type Mission @key(fields: "id") {
    id: ID!
    crew: [Astronaut]
    designation: String!
    startDate: String
    endDate: String
}

type Astronaut @key(fields: "id") @extends {
    id: ID! @external
    missions: [Mission]
}

The queries and mutations which are exposed to the gateway are:-

type Query {
	getMission(id: ID!): Mission
	queryMission(filter: MissionFilter, order: MissionOrder, first: Int, offset: Int): [Mission]
	aggregateMission(filter: MissionFilter): MissionAggregateResult
}

type Mutation {
	addMission(input: [AddMissionInput!]!): AddMissionPayload
	updateMission(input: UpdateMissionInput!): UpdateMissionPayload
	deleteMission(filter: MissionFilter!): DeleteMissionPayload
	addAstronaut(input: [AddAstronautInput!]!): AddAstronautPayload
	updateAstronaut(input: UpdateAstronautInput!): UpdateAstronautPayload
	deleteAstronaut(filter: AstronautFilter!): DeleteAstronautPayload
}

The queries for Astronaut are not exposed to the gateway since it will be resolved through the _entities resolver. Although these queries will be available on the Dgraph GraphQL endpoint.

Mutation for extended types

if we want to add an object of Astronaut type which is @Extended in this service.
The mutation addAstronaut takes AddAstronautInput which is generated as:-

input AddAstronautInput {
	id: ID!
	missions: [MissionRef]
}

Even though the id field is of ID type which should be ideally be generated internally by Dgraph, In this case, it should be provided as input. The reason for this is because of the unavailability of federated mutations, the user should provide the value of id same as the value present in the GraphQL service where the type Astronaut is defined.
For example, let's take that the type Astronaut is defined in some other service AstronautService as:-

type Astronaut @key(fields: "id") {
    id: ID! 
    name: String!
}

When adding an Object of Astronaut type, first it should be added into AstronautService and then the addAstronaut mutation should be called and value of id provided as an argument must be equal to the value in AstronautService.

Gateway Supported Directives.

Due to the bug in the federation library (see here), some directives are removed from the schema SDL which is returned to the gateway in response to the _service query.
Those directives are @custom, @generate, and @auth.
You can still use these directives in your GraphQL schema and they will work as desired but the gateway will unaware of this.


This change is Reviewable

Fix GRAPHQL-905.
This PR implements [Federation Schema Specification](https://www.apollographql.com/docs/federation/federation-spec/#federation-schema-specification) in order to support apollo federation.
Fixes GRAPHQL-934.
This PR adds `_service` resolver according to the federation specs which return generated schema string without @apollo directives to be used by the gateway.
The query is:
```
query {
   _service {
      sdl
   }
}
```
which returns the schema string.
@github-actions github-actions bot added the area/graphql Issues related to GraphQL support on Dgraph. label Jan 12, 2021
Fixes GRAPHQL-951.
This PR modifies GraphQL generated schema in order to support federation.
It also removes some directive definitions which currently give validation error in apollo.
This PR also removes generated mutations and mutation input types from the Generated schema.
Fixes GRAPHQL-922.
This PR adds `entity` resolver which resolves `_entities(representation: [Any]!)` queries which are sent by the gateway to the graphql service.
@netlify
Copy link

netlify bot commented Jan 22, 2021

Deploy preview for dgraph-docs ready!

Built with commit 359bac4

https://deploy-preview-7275--dgraph-docs.netlify.app

minhaj-shakeel and others added 7 commits January 27, 2021 12:10
Fixes GRAPHQL-968.
This PR does two things.
1 - It exposes the `mutations` to the apollo gateway which were earlier restricted. It exposes mutations for both `type definitions` as well as `type extensions`. Whereas `queries` for the `extended types` are `not exposed` as they are resolved through `entity resolver`.
2 - It adds support for add mutation on extended type having field with `ID` type as @key field. In this case the field is stored internally in the dgraph as `string` type so its value needs to be given as an argument inside the mutation.
Copy link
Contributor

@pawanrawal pawanrawal left a comment

Choose a reason for hiding this comment

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

Reviewed 19 of 36 files at r1, 11 of 14 files at r2, 2 of 2 files at r3, 8 of 8 files at r4.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @minhaj-shakeel)


graphql/admin/admin.go, line 860 at r4 (raw file):

					defer as.mux.RUnlock()
					sch := as.schema.Schema
					handler, _ := schema.NewHandler(sch, false, true)

Is the second argument error, what if there is an error?


graphql/dgraph/graphquery.go, line 153 at r4 (raw file):

		x.Check2(b.WriteString(fmt.Sprintf("(func: type(%s)", q.Func.Args[0].Value)))
	case q.Func.Name == "eq":
		x.Check2(b.WriteString("(func: eq("))

Can you add a comment here saying that for resolving _entities query, multiple arguments for eq would be required?

Copy link
Contributor Author

@minhaj-shakeel minhaj-shakeel left a comment

Choose a reason for hiding this comment

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

Reviewable status: 38 of 40 files reviewed, 2 unresolved discussions (waiting on @pawanrawal)


graphql/admin/admin.go, line 860 at r4 (raw file):

Previously, pawanrawal (Pawan Rawal) wrote…

Is the second argument error, what if there is an error?

Handled error properly.


graphql/dgraph/graphquery.go, line 153 at r4 (raw file):

Previously, pawanrawal (Pawan Rawal) wrote…

Can you add a comment here saying that for resolving _entities query, multiple arguments for eq would be required?

Done.

@minhaj-shakeel minhaj-shakeel merged commit 1e6af7e into master Jan 28, 2021
@minhaj-shakeel minhaj-shakeel deleted the minhaj/apollo-federation branch January 28, 2021 07:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/graphql Issues related to GraphQL support on Dgraph.
Development

Successfully merging this pull request may close these issues.

3 participants