-
Notifications
You must be signed in to change notification settings - Fork 65
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
Proposal: Ballerina GraphQL Federation Support #3504
Proposal: Ballerina GraphQL Federation Support #3504
Comments
The proposal has been modified with a different approach to resolve entity reference as ballerina language doesn't allow the invocation of instance methods without an instance |
|
@MohamedSabthar @ThisaruGuruge why aren't |
It seems that I am having difficulty understanding the question. Just to clarify, are you asking if it is possible to enable entities in a subgraph by providing a |
One alternative is to add it as a |
Summary
The current implementation of the ballerina graphql module doesn’t support graphql federation. To enable the graphql federation the ballerina graphql module should support implementation of subgraphs specified by Apollo subgraph specification. This proposal focuses on the API design of ballerina graphql subgraphs.
Goals
Non-Goals
Motivation
It is a common practice to create a collection of subgraphs and then merge them into a single supergraph when performing large deployments. This practice offers means of splitting monolithic GraphQL servers into independent microservices (subgraphs) which can be independently scaled and managed by responsible teams. This is commonly done following Apollo Federation specifications. The gateway can resolve a client query by connecting to these subgraphs and executing a query plan. It would be ideal if the ballerina graphql module could provide a straightforward method for implementing these subgraphs.
Description
GraphQL Federation helps to split monolithic GraphQL servers into independent microservices. The federation consists of two main components.
Each independent microservice holds a part of the GraphQL schema and the gateway merges the schema into a single composed schema. In other words, these independent microservices create subgraphs which are combined by the gateway to create a supergraph. This supergraph can be consumed by the client application by connecting to the gateway.
A ballerina graphql service must do all of the following three steps to operate as a apollo federation 2 subgraph.
1. Automatically extend its schema with all definitions listed here
This can be done by introducing a
@graphql:Subgraph
annotationThis annotation can be checked at runtime, and the schema can be extended with the additional types/directives necessary while the service is attached to the listener. If the
@graphql:Subgraph
annotation is not added to the service, the schema extension procedure can be bypassed. Minimum functionality to support Apollo federation at least requires implementation of@link
,@key
directives and implementation of following types2. Correctly resolve the
Query._service
enhanced introspection fieldSome federated graph routers can compose their supergraph schema dynamically at runtime. To allow routers to compose their schema in runtime following types should be added or modified in the generated schema.
The aforementioned types can be added on demand by checking the proposed
isSubgraph
field in the service configuration annotation. No additional API needs to be added for this step.Querying the
_service.sdl
field should return the schema string in the SDL language. This string should contain all instances of federation directives such as@key
,@sharable
, and so on. This improved introspection can be implemented into ballerina graphql by extending the SDLFileGenerator class's existing implementation. The current implementation of this class does not take federation directives into account while producing the SDL schema. As a result, the extension of this class will include additional logic to incorporate the federated directives.3. Provide a mechanism to resolve entity fields via the
Query._entities
fieldEntity
An entity is an object type that can resolve its fields across multiple subgraphs. Each subgraph can contribute different fields to the entity and is responsible for resolving only the fields that it contributes.
To fully define an entity within a subgraph, following 2 steps are required.
@key
directive to a type to make it as an entity- This directive defines the entity's primary key, which consists of one or more of the type's fields. This directive effectively tells the router, "This subgraph can resolve an instance of this entity if you provide its primary key."These two steps can be incorporated in ballerina graphql using the following proposed API
API
The first step can be done by introducing a new
@graphql:Entity
annotation in graphql moduleThis annotation can be attached to a service class (GraphQL OBJECT) or service object (GraphQL INTERFACE)
Step two can be achieved by supplying a function pointer to the
resolveReference
field of the@graphql:Entity
annotation.Ex:
ReferenceResolver
ornil
(if not resolvable).key
fields, plus its__typename
field. These values are provided by the router.__typename
andprimary-key
. The engine will invoke the referenceResolver of the entity specified by__typename
.Ex: Defining an Entity in ballerina graphql
Any number of different subgraphs can contribute fields to an entity definition.
Ex: Same Product entity defined in a different ballerina graphql subgraph.
Subgraphs can use an entity as the return type of a field without adding any fields to that entity.
In this situation, a stub implementation of the entity must be included to build a valid schema, as seen below.
Ex: Entity stub implementation using class
A record type can also be used as an entity
Ex: Entity stub implementation using record
The GraphQL compiler plugin collects all entities annotated with
@graphql:Entity
, then modifies the user code by creating a union type calledEntity
. Additionally, the produced GraphQL schema will include a GraphQL union type named_Entity
, as required by the router in the Apollo subgraph specification.Additionally, the GraphQL compiler plugin (code modifier) modifies the root GraphQL service by adding the following resource function which includes the logic for invoking the reference resolvers of each entity.
Future Plans
With the notable exception of
@key
fields, each subgraph must contribute different fields by default. Otherwise, a composition error occurs. To override this behavior, Ballerina graphql might introduce the following annotations, which can be applied to objects/class methods.@graphql:Shareable
@graphql:Provides
@graphql:External
For more details about the corresponding directives of the above annotations see resolving-another-subgraphs-field.
Following example show the usage of
@graphql:Shareable
annotationFollowing are a few additional federated directives defined in the apollo subgraph specification. These are useful for advanced use cases. These directives could also be implemented using ballerina annotations.
@requires(fields: FieldSet!)
@inaccessible
@override(from: String!)
@requires(fields: FieldSet!)
@tag(name: String!)
@key
Testing
A ballerina graphql subgraph might be tested by performing introspection on individual subgraphs. Further testing can be done using apollo-federation-subgraph-compatibility testing-suite.
Dependencies
#3286
The text was updated successfully, but these errors were encountered: