Wednesday, September 12, 2018

GraphQL



https://github.com/apollographql/graphql-subscriptions
https://graphql.org/blog/subscriptions-in-graphql-and-relay/
Event-based subscriptions #
the client can tell the server what data it wants to be pushed with the subscription with a GraphQL selection.
subscription StoryLikeSubscription($input: StoryLikeSubscribeInput) {
  storyLikeSubscribe(input: $input) {
    story {
      likers { count }
      likeSentence { text }
    }
  }
}
The client would then send this subscription to the server, along with the value for the $input variable, which would contain information like the story ID to which we are subscribing:
input StoryLikeSubscribeInput {
  storyId: string
  clientSubscriptionId: string
}
At Facebook, we send this query to the server at build time to generate a unique ID for it, then subscribe to a special MQTT topic with the subscription ID in it, but many different subscription mechanisms could be used here.


https://blog.apollographql.com/batching-client-graphql-queries-a685f5bcd41b
Batched operations are always as slow as the slowest operation in the batch
https://blog.apollographql.com/layering-graphql-on-top-of-rest-569c915083ad
Querying many resources and retrieving the exact data you want in one request.
  1. Improved performance, especially on devices with slow network connections via reduced payload size and less round trips to the server.

[Apollo Client](https://github.com/apollographql/apollo-client)

https://blog.apollographql.com/graphql-vs-rest-5d425123e34b
One thing to note in REST is that the type, or shape, of the resource and the way you fetch that resource are coupled. When you talk about the above in REST documentation, you might refer to it as the “book endpoint”.
GraphQL is quite different in this respect, because in GraphQL these two concepts are completely separate. In your schema, you might have Book and Author types:
That’s one core difference between REST and GraphQL — the description of a particular resource is not coupled to the way you retrieve it.
To be able to actually access a particular book or author, we need to create a Query type in our schema:
type Query {
  book(id: ID!): Book
  author(id: ID!): Author
}

First of all, we can see that the URL with a GraphQL query specifies the resource we’re asking for and also which fields we care about. Also, rather than the server author deciding for us that the related author resource needs to be included, the consumer of the API decides.
But most importantly, the identities of the resources, the concepts of Books and Authors, are not coupled to the way they are fetched. We could potentially retrieve the same Book through many different types of queries, and with different sets of fields.
  • Similar: Both have the idea of a resource, and can specify IDs for those resources.
  • Similar: Both can be fetched via an HTTP GET request with a URL.
  • Similar: Both can return JSON data in the request.
  • Different: In REST, the endpoint you call is the identity of that object. In GraphQL, the identity is separate from how you fetch it.
  • Different: In REST, the shape and size of the resource is determined by the server. In GraphQL, the server declares what resources are available, and the client asks for what it needs at the time.

  • Similar: The list of endpoints in a REST API is similar to the list of fields on the Query and Mutation types in a GraphQL API. They are both the entry points into the data.
  • Similar: Both have a way to differentiate if an API request is meant to read data or write it.
  • Different: In GraphQL, you can traverse from the entry point to related data, following relationships defined in the schema, in a single request. In REST, you have to call multiple endpoints to fetch related resources.
  • Different: In GraphQL, there’s no difference between the fields on the Query type and the fields on any other type, except that only the query type is accessible at the root of a query. For example, you can have arguments in any field in a query. In REST, there’s no first-class concept of a nested URL.
  • Different: In REST, you specify a write by changing the HTTP verb from GET to something else like POST. In GraphQL, you change a keyword in the query.

  • Similar: Endpoints in REST and fields in GraphQL both end up calling functions on the server.
  • Similar: Both REST and GraphQL usually rely on frameworks and libraries to handle the nitty-gritty networking boilerplate.
  • Different: In REST, each request usually calls exactly one route handler function. In GraphQL, one query can call many resolvers to construct a nested response with multiple resources.
  • Different: In REST, you construct the shape of the response yourself. In GraphQL, the shape of the response is built up by the GraphQL execution library to match the shape of the query.
https://medium.freecodecamp.org/so-whats-this-graphql-thing-i-keep-hearing-about-baf4d36c20cf
In a nutshell, GraphQL is a syntax that describes how to ask for data, and is generally used to load data from a server to a client. GraphQL has three main characteristics:
  • It lets the client specify exactly what data it needs.
  • It makes it easier to aggregate data from multiple sources.
  • It uses a type system to describe data.







For example, imagine you need to display a list of posts, and under each post a list of likes, including user names and avatars. Easy enough, you tweak your posts API to include a likes array containing user objects:

But now, it’s time to work on your mobile app, and it turns out loading all that extra data is slowing things down. So you now need two endpoints, one with the likes and one without them.
Now add one more factor to the mix: it turns out that while posts are stored in a MySQL database, likes on the other hand live in a Redis store! What do you do now?!
The solution Facebook came up with is conceptually very simple: instead of having multiple “dumb” endpoints, have a single “smart” endpoint that can take in complex queries, and then massage the data output into whatever shape the client requires.

https://medium.com/workday-engineering/real-world-reasons-to-use-graphql-d70cff1bcd9c
Using REST APIs, client development for complex, multi-platform, data-driven applications like SkipFlag has traditionally required (or at least frequently resulted in) a bunch of custom endpoints. Custom endpoints are difficult to keep consistent, onerous to test, and duplicate code.
With GraphQL, the API specifies all of the data that is available, and each client requests exactly what it needs. This allows client development to move faster and more independently.
Have a mobile view that uses a limited set of fields of a type? GraphQL only retrieves the fields requested. Need to make a batch request for several objects (or several different types)? GraphQL allows the use of aliases instead of having to explicitly create batch APIs:

2. Relay (and other great client frameworks)


https://www.baeldung.com/spring-graphql
https://graphql.org/
https://graphql-java.readthedocs.io/en/latest/index.html

https://about.sourcegraph.com/graphql/graphql-at-twitter/

https://github.com/graphql-java/graphql-java-http-example/blob/master/src/main/java/com/graphql/example/http/HttpMain.java

https://github.com/howtographql/graphql-java
https://www.howtographql.com/graphql-java/0-introduction/
graphql-java-tools defines two types of classes: data classes, which model the domain and are usually simple POJOs, and resolvers, that model the queries and mutations and contain the resolver functions. Often, both are needed to model a single GraphQL type.

Query models behavior, as it contains the resolver for the allLinks query.
type Query {
  allLinks: [Link]
}

@WebServlet(urlPatterns = "/graphql")
public class GraphQLEndpoint extends SimpleGraphQLServlet {

    public GraphQLEndpoint() {
        super(buildSchema());
    }

    private static GraphQLSchema buildSchema() {
        LinkRepository linkRepository = new LinkRepository();
        return SchemaParser.newParser()
                .file("schema.graphqls")
                .resolvers(new Query(linkRepository))
                .build()
                .makeExecutableSchema();
    }
}


GraphiQL is an in-browser IDE allowing you to explore the schema, fire queries/mutations and see the results.

type Mutation {
  createLink(url: String!, description: String!): Link
}
public class Mutation implements GraphQLRootResolver {
    
    private final LinkRepository linkRepository;

    public Mutation(LinkRepository linkRepository) {
        this.linkRepository = linkRepository;
    }
    
    public Link createLink(String url, String description) {
        Link newLink = new Link(url, description);
        linkRepository.saveLink(newLink);
        return newLink;
    }
}

Since resolvers are responsible for fetching the value of a single field, it is easy to imagine that, within a single query response, values could be coming from multiple storages and third-party APIs at the same time, without the client ever being affected.

graphql-java offers BatchedExecutionStrategy, which looks for resolvers (DataFetchers in graphql-java lingo) annotated by @Batched. Such resolvers are expected to take a list of source objects and return a list of results. For the example above, that would mean taking a list of links (List<Link>) and returning a list of descriptions (List<String>). Update: graphql-java-tools now supports batched data fetchers as of this commit

For signing in, you’ll need another mutation (as it is a side-effect producing action). The mutation will expect email and password and it will return a token to be used for authenticating subsequent requests.
https://piotrminkowski.wordpress.com/2018/08/16/graphql-the-future-of-microservices/


We can easily enable support for GraphQL on the server-side Spring Boot application just by including some starters. After including graphql-spring-boot-starter the GraphQL servlet would be automatically accessible under path /graphql. We can override that default path by settings property graphql.servlet.mapping in application.yml file. We should also enable GraphiQL – an in-browser IDE for writing, validating, and testing GraphQL queries, and GraphQL Java Tools library, which contains useful components for creating queries and mutations. Thanks to that library any files on the classpath with .graphqls extension will be used to provide the schema definition.
Every schema definitions contains data types declaration, relationships between them, and a set of operations including queries for searching objects and mutations for creating, updating or deleting data. Usually we will start from creating type declaration, which is responsible for domain object definition. You can specify if the field is required using ! char or if it is an array using [...]. Definition has to contain type declaration or reference to other types available in the specification.
1
2
3
4
5
6
7
8
9
type Employee {
  id: ID!
  organizationId: Int!
  departmentId: Int!
  name: String!
  age: Int!
  position: String!
  salary: Int!
}
schema {
  query: EmployeeQueries
  mutation: EmployeeMutations
}
type EmployeeQueries {
  employees: [Employee]
  employee(id: ID!): Employee!
  employeesByOrganization(organizationId: Int!): [Employee]
  employeesByDepartment(departmentId: Int!): [Employee]
}
type EmployeeMutations {
  newEmployee(employee: EmployeeInput!): Employee
  deleteEmployee(id: ID!) : Boolean
  updateEmployee(id: ID!, employee: EmployeeInput!): Employee
}
input EmployeeInput {
  organizationId: Int
  departmentId: Int
  name: String
  age: Int
  position: String
  salary: Int
}


https://brandur.org/graphql
There’s no wildcard operator like a SELECT * from SQL. Compared to REST, this has an advantage of reducing payload size (especially helpful for mobile), but more importantly, it establishes an explicit contract between the client and server which allow APIs to be evolved more gracefully.

GraphQL is automatically introspectable online. By using the special __type operator, any client can get a detailed understanding of a type and all its fields and documentation:
{
  __type(name: "User") {
    name
    fields {
      name
      type {
        name
      }
    }
  }
}

GraphQL models objects as a graph. Technically, the graph starts with a root node that branches into query and mutation nodes, which then descend into API-specific resources.
GraphQL takes existing API paradigms to a logical conclusion. Almost every REST API that exists today is already a graph, but one that’s more difficult to traverse.
Stripe’s API has a concept called object expansion that lets a user tell the server that it would like an ID (e.g., cus_123) expanded into its full object representation by passing an expand[]=... parameter in with the request. Expansions are chainable, so I can ask for charge.customer on a dispute to reveal the dispute’s associated charge, and that charge’s customer. The feature’s most common effect is saving API calls – instead of having to request two objects separately, just one request can be made for the first object with the second embedded. Users make extensive use of this feature – we constrain expansions to three levels deep, but get regular requests to allow up to four levels.
Every sufficiently long-lived web API that responds to user feedback will eventually evolve a batch API.
In REST APIs, that involves building a custom batch specification because there’s nothing even close to wide standardization for such a thing. Users adapt to each exotic implementation by reading a lot of documentation. In GraphQL, batch queries are built right in. Here’s a document containing multiple operations on the same query and which uses aliases (userAuserB) so that the results are disambiguated in the response:
userA: getUser(id: "user_123") {
  email
}

userB: getUser(id: "user_456") {
  email
}
Batch mutations are also allowed.
The availability of this feature doesn’t necessarily give users free reign the ability to run costly batch requests. Remember that as an API provider, you can still put restrictions on this within reason. For example, by allowing only five operations per request (if that’s the right fit for you), or even just one.

Explicitness and graceful enhancement

I mentioned above how fields in GraphQL must be requested explicitly and that there’s no SQL-like glob operator (SELECT *) to get everything. This might be GraphQL’s most interesting feature because it lends itself so well to API versioning and enhancement.
In a REST API, an API provider must assume that for any given API resource, every field is in use by every user because they have no insight at all into which ones they’re actually using. Removing any field must be considered a breaking change and an appropriate versioning system will need to be installed to manage those changes.
https://brandur.org/api-paradigms
At Stripe for example, our resource updates should use PATCH instead of PUT, but for historical reasons they don’t, and it’s probably not worth changing at this point. Developers will need to read the documentation anyway, and they’ll find out about our ubiquitous use of the POST verb when they do.
REST also has other problems. Resource payloads can be quite large because they return everything instead of just what you need, and in many cases they don’t map well to the kind of information that clients actually want, forcing expensive N + 1 query situations. This is especially bad for clients on more limited networks like mobile, where bandwidth and bad latency conspire to make REST an expensive proposition.

built-in introspection so developers can use tools to navigate through an API they’re about to use. Data can be organized in a free form way that doesn’t necessarily tie it to heavy resources. A well-organized graph can allow a client request the exact set of data they need to do their work, with little waste in number of calls or payload size. Imagine having to send only a single API request out to load a page instead of dozens. It’s great for service operators too, because its explicitness allows them to get a better understanding of exactly what their users are trying to do.


One possibility for the next big paradigm in APIs is just to make them a set RPCs (remote procedure calls) and use something like GRPC to generate libraries in a huge variety of languages that users can pull down and use at their leisure. Under GRPC, data moves around in the efficient protocol buffers format over HTTP2, making transport performance of a GRPC-based API good by default, and with no effort required on the parts of either users or operators.


Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts