#technology #engineering #integration #api #query #microservice
idea
GraphQL is a query language for APIs. It defines how the API can be called for query or mutating entities.
It's based on a set of type declarations[1] describing the entities that the API can serve, and their corresponding relationships.
Queries can then be made on these entities, and specify what needs to be retrieved[2] from the system, including from sub-types. GraphQL then returns it using json[3].
The GraphQL library itself is only a parser. Processing the queries is done using a resolver[4] which retrieves the data necessary to fulfill the request.
A GraphQL layer helps abstracting the underlying infrastructure and represents it under a more functional view. It also allows to compose data coming from multiple services as one, while providing a good framework to allow some relational querying across multiple services.
Some principles[3] to build a GraphQL API:
- One graph, not many, in order to offer a consistent interface
- Federated rather than centralize, to prevent bottlenecks and favor speed
- Use a schema registry
- Manage access control and demand (throttling)
- Capture logs of all graph operations
- Adopt a layered approach, with the data graph layer separated from the service implementation
GraphQL federation[2] is a way to support integration to each of the services of a system and presenting a single Graph. This includes a single gateway but a service implementing the resolver for each of the domains.
links
references
[2]: Netflix Tech Blog / How Netflix Scales its API with GraphQL Federation (Part 1)ref Netflix is using a federated graphQL gateway which permits to show one graph to all consumer, but retain the aspects of decoupling and distributing work.
It has several key aspects:
- A single GraphQL gateway under control of a single team, with an associated schema. It reviews incoming requests and create execution plans to retrieve data from all the sub-services. It also manages registration of schemas and composes all domains into one unified schema.
- Domain Graph Services (DGS) which offer standalone GraphQL services capable of resolving a query for a given domain.
- Entities that are a federated type, i.e. are partially defined across several domains (e.g. the production domain defines a
production
attributes for themovie
entity)
[3]: Apollo / Principled GraphQL is presenting a set of principles to build GraphQL apis following a format inspired by Twelve Factor App.
examples
- [1]: Example of a type definition:
type Query {
person(id: ID): Person
}
type Person {
id: ID
firstName: String
lastName: String
notes: [Note]
}
type Note {
id: ID
content: String
author: Employee
}
type Employee {
id: ID
name: String
alias: String
}
-[2]: Example of a query
query getPersonAndNotes{
person(id: 4) {
id
firstName
notes {
content
author {
alias
}
}
}
}
- [3]: Example of the corresponding response
{
"data": {
"person": {
"id": "4",
"firstName": "Yurko",
"notes": [
{
"content": "Note from Jordan about Yurko",
"author": {
"alias": "jfranco@"
}
},
{
"content": "Note from Maria about Yurko",
"author": {
"alias": "mdelan@"
}
},
{
"content": "Note from Piotr about Yurko",
"author": {
"alias": "pgut@"
}
},
{
"content": "Note from Sanah about Yurko",
"author": {
"alias": "spirte@"
}
}
]
}
}
}
- [4]: example of a resolver
class Resolver {
person({ id }) {
const person = data.persons[id]
person.notes = () => this.notes(id)
return person
}
notes(personId) {
return data.notes
.filter(note => note.personId === personId)
.map(note => {
const n = note
n.author = () => this.employee({ id: n.employeeId })
return n
})
}
employee({ id }) {
const employee = data.employees[id]
return employee
}
};