Moving Existing API From REST To GraphQL

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone my name is Brooks I am a platform engineer at github we're the team that I'm on works on our api's and web hooks and today in the theme of developer happiness I'd like to talk about optimizing api's for consumers with graph QL but before we dive into graph QL let's start with api's and more specifically rest api's I'm curious by a show of hands how many of you have written code that consumes a REST API awesome cool how many of you have written your own REST API dang awesome cool and how many of you before today have heard of graph QL dang that's amazing ok awesome so throughout today's talk I'd like to use this particular API as a point of reference this is an API that I put together about a year ago and it's a wrapper around an NYC open data set for health inspections of restaurants here in New York City and for anyone who's just visiting New York City for the conference basically whenever you walk into a restaurant they're required to post their letter grade their health rating sorry the the letter grade of the last inspection that they received and so when looking at a REST API specifically a request for a request for a REST API there's a few components to it the first is an HTTP verb or method and that specifies the operation that we'd like to take against the API and the second is an endpoint which is an identifier that allows us to specify the part of the API that we'd like to interact with so if we execute this request we'll get back a response that looks like this in this particular case this API returns back JSON and it's comprised of resources so if we take a look at what one of those resources might look like we can see that there's a few components to the response the first are attributes these are things like the name the address of the restaurant the cuisine that has been categorized as and in some cases you'll also see hyper media and hyper media is a machine-readable link to another place in the API about information related to the resource so you can see on the bottom there we have inspections URL and if we follow that link we can get more information about the inspections that the first restaurant has received in this case we have a new resource that we're dealing with so if we execute that request you'll notice that we get again attributes and more hypermedia and if we follow this link this is all of the violations that they received during a given inspection so again as we make these more requests we can build the full picture of data that we as clients may need in order to build an application we execute that request again we get back some attributes in some hypermedia but if you imagine us as a desktop application you can see that it takes numerous requests for us to determine the information that we may need as a client right we have to make numerous HTTP requests in order to get all the info that we need and this is especially painful when you're working with say a mobile client which might be working off a super slow connection so rest api's are optimized around servers and not necessarily clients they're modeled around the resources that they return which makes them general-purpose and reusable from client to client and honestly that's one of rests biggest strengths but the question that I posed to us as API designers everyone who raised your hand just now if you've written a REST API is what if we wanted to put our clients first what if we wanted a better developer experience for the people that are consuming these api's so one in one pattern for that is Baden's for front ends it was something that was popularized by Netflix and reused commonly and the general idea is for each particular device that accesses say Netflix is API they have their own separate endpoint the only thing is this can become a little bit problematic when you have to start to deal with like deep pagination for example if you have a complex object relationship that gets returned in this one endpoint it can be really hard to have to iterate over all of the different say restaurants and all of their inspections and all of their violations and this could be even harder when you have to iterate on that endpoint say that there's a new device that was released a new Apple TV that has a fancy new version of the Netflix application the older devices that haven't been updated end up getting all of this new information that they not may not be using and this also only really works if you as the API designer are in control of the client and you completely understand the data requirements that that client may need and what about in the case of a public API where you may not know anything about the data requirements of your clients well that's where graph QL comes in it's a data query language for your API so think of it as sequel which is the lowest common denominator between technologies like my sequel Postgres MS sequel and think of it less as neo4j which is an entire craft datastore in its own right so graph QL is a query language specification it's been implemented in a variety of different languages like Ruby JavaScript Python and so on and the language was originally created by Facebook to help with the data access needs of their mobile clients so here's the hello world of graph QL you'll notice right off the bat that it bears some resemblance to JSON it almost looks like it's JSON but without any of the values and that's very much on purpose and we'll see why in a few so there's a few different components to a graph QL query the first shown here is what we call a selection set and me represents the currently authenticated user and for the currently authenticated user ID like to fetch the first name last name and email we call these fields so if you execute this query against a graph QL server you'll get back a response that looks like this in this case again it's JSON and you'll notice that the query defines the structure of the response and that's a really important part to graph QL so going back to our NYC restaurant grades example we still have an HTTP verb and we still have an endpoint but that's pretty much where the similarities with rest end and the reason that we have to use an HTTP POST is because the client has to send information to the server in this case it's the the query that we would like the server to execute so if we look at an example for this particular API you can see that this looks a little bit like the hello world example but we're now talking about restaurants and there's a new concept here in graph QL called an argument we're basically saying I'd like to fetch the name of a restaurant called cafe Gia and an argument as a way for us to pass eleven information to the server and that way there the server can modify the response based on the information that we're looking for so if we execute this again we get a response that's very much structured like the query so let's take a look at some of the features of the query language the first is that graph QL is typed and the type system is a product of your application code so if we look back to the original hello world example behind the scenes there's actually a schema and it's the schema that graph QL is querying we call this an IDL you can think of it as a database schema but instead of describing the structure of your database we're describing the structure of what we can query so if we break down this query we can see that each part has a corresponding entry in the schema the first is me which returns a user type which is defined down there below the user type implements three fields first name last name and email all of which return what we call a scalar value it's just a plain old string so if we look back to our NYC restaurant grades example here's the corresponding schema for it breaking down each part of this schema we can see that it starts with the top-level restaurant right there which takes an argument a name of string and what's really neat about having a type system in place with graph QL is that you can determine whether or not a query is valid right off the bat if someone sends to you anything other than a string for this named argument we know that we can just fail the request and say no sorry I don't support that and the restaurant type which is defined down below returns both a name and a cuisine both of which are string but you'll notice that there is a bang next to the name entry that is basically with a way of denoting that you will always get back a value for that it's non knowable but what if we wanted to return a list of objects well in this particular case we can use restaurants plural which is something that this particular API supports and you'll notice that the argument here is different from the previous example where we have Brooklyn and all caps and this query is utilizing a graph QL feature called an enum an enum is a way to specify a list of possible values so if we look the corresponding schema for this we can see at the topmost level we return restaurants which take in an argument of restaurant borough and what's nice about an enum is that we can specify exactly what's supported it doesn't make sense for this particular application to take anything other than these five boroughs and then finally we return a list of restaurants each of which has a field name and cuisine so what if we wanted to fetch two restaurants by their name you can imagine that the response would look something like this right because the query defines the shape of the response but you'll notice that we have a key conflict which I'm pretty sure is legal JSON but would totally wreck havoc in Ruby and so what graph Kuehl allows us to do is alias field names and they can be used to rename a particular subset of the query to something else so if we look at what this may look like as a response you can see that instead of having our duplicated restaurant field names now they're using the alias field names and one more thing that you'll notice about that previous example is that there's some duplication which isn't great name and cuisine is reused well what graph Kuehl allows us to do is create what's called a fragment so down on the bottom we define a fragment we call it restaurant info and you have to specify which type that it's defined on now once you have the fragment we can define what the things that we'd like to fetch in this case name and cuisine and then we've reused that fragment with this dot dot dot notation towards the top now another point in part to graph QL is that it's introspect able meaning that graph QL is capable of telling you all of the different things that it can that it's capable of returning and that means that things like documentation and client generation come for free now one tool that utilizes the power of that of the type system my introspection is graphical which God willing I would like to live demo so this is the part where I ask that everyone make like a silent prayer that this live demo goes well all right so let's see this working cool everybody see that so this is graphical there's two main parts to it on the left hand side we can craft a query on the right hand side we can see what the response would be I'm just pointing this to a local rail server that I have running and let's give it a shot so let's say we want to fetch a particular restaurant so you'll notice as I start typing that graphical offers like Clippy like suggestions and that's because it's reusing the power of introspection because the graphical server is capable of telling us all of the different things that it can query it knows ahead of time in its context aware so based on where my cursor is it can offer suggestions so I'll tap autocomplete and let's say that I'm looking for a particular restaurant this this one used to be my favorite restaurant until I started working on this talk okay so let's say that we want to fetch its address for example I hit command enter you can also hit play here and basically what that returns is just the address of this particular restaurant but let's say that I want to add more fields and I don't know what's available to me well graphical has this built in documentation Explorer on the right-hand side and again this is reusing the power of graph QL introspection features so if we dive into the root query for example we can see that these are all of the things at the topmost level that are made available to us if we dive down into restaurant you can see this is that IDL like structure that we were just seeing where we can take a name argument or a borough argument and return a restaurant object so if we return if we take a look at the restaurant object these are all of the different fields that we can query so let's say that we want to fetch its cuisine and pretty sure it's Italian cool so let's try something a little bit more complex let's say that we want to fetch all of the restaurants with a name of Subway in the borough of Manhattan so now because we're using restaurants plural we're going to get back a list of all these restaurants let's say that we again want to reuse the address and cuisine and now we get back a JSON response of all the restaurants of Subway's in man but if you notice there's some more information that we can fetch on the restaurant type for example inspections and the rent again this is a whole list of inspection types so let's take a look at all of the inspections of each of these inspection has things like grade when it was created inspected at so let's say let's get the last time that they were inspected and maybe the grade that they received cool so we get back a z' in most parts bees don't go to that one and so we get back a of structured response based on the things that are in our query we've defined that we're allowed to have and you can also dive in to say violations this is where all the really good stuff is so descriptions are basically a list of all the violations that you got in human readable form some bad contact surfaces nobody's washing their hands at that one my spill flies I still up subway ok cool so let's dive back into keynote there cool awesome so one of the things that I was hoping to point out what that live demo is the idea that you can fetch multiple resources in one roundtrip so contrast that to earlier where we had our desktop client which had to make numerous requests to numerous endpoints to build up the full picture of data that we as a client may need and contrast that again to the backends for front-ends model where each particular device has its own endpoint now each of those devices can utilize this same one graph QL endpoint so let's talk about what it takes to implement a graph QL server so the NYC restaurant grades website is just a rails app when we send a request to slash graph QL we end up at a pretty regular lookin controller this controller starts by taking the query out of the params it's just a plain old string and it passes us two it passes it to our schema to be executed once we get a result from the schema we've render it as JSON and serve that back up to the client that requested it but in order to do all of this we need a graph QL implementation we need the graph schema execute part and like sequel there are many different implementations today I want to talk about the Ruby one because this particular application is a rails app and this is guru Co so the de facto gem for graph QL is aptly named graph QL Ruby is created by Rob masago and it allows us to define our graph QL schemas in Ruby so let's take another look at that restaurant query that we were looking at before and remember that it has schema definition that looks something like this it starts off with the root query at the top the restaurant field returns a restaurant object and it has an argument which it takes an argument named string but what would this look like in Ruby well let's start by taking just the top level just the root query and set aside the restaurant field to start so it would look something like this in Ruby you can see that we define a new graph QL object type and we set the object's name to require e this is the DSL of graphical Ruby it's it's relatively straightforward now one thing that I've emitted from almost all of my slides just for the sake of space is documentation you can use the description DSL down on the bottom there to annotate your schema with various different descriptions and that's how graphical was fetching all of its information on the right hand side in the documentation Explorer ok so moving on to the restaurant fields what would this look like in Ruby well it's a little bit more complex but let's break it down step by step we start by defining the name of the field that's returned then we have to pass the argument we define that it must always be a string and again this is the part where graph QL can validate that you're always getting sane input after that we have to specify the return type and in this case I'm passing an entire Ruby object in this case it's the Ruby schema definition for restaurant because remember restaurant has a bunch of fields of its own that it can implement and finally we have to tell the schema how to fetch the underlying data and at the heart of every field definition is something called the resolver in this case I'm just calling out to active record I'm doing a restaurant dot fine by and I'm passing in the argument that was passed by the user inside of this query and so once we get back our result the schema starts to look for the restaurant definition and we haven't defined that yet so let's look at what that looks like so this is our restaurant type remember it had at least name in cuisine both of which return a string and again we start off by defining the graph QL objects name we can specify a description to have it show up inside of the documentation Explorer but what about this cuisine fields which returns a string well again we start by defining the name of the fields we return we specify the return type in this case it's just a plain old string there's no more selections that you can make on the cuisine field and it just returns a scalar value and finally we have to tell the schema how to fetch the restaurants cuisine in a resolver and so in this particular case this lowercase restaurant is just the active record object that we got back from the previous resolver we passed those through from resolver to resolver until we end up with the result that we'd like to have and so this is an important part that graph QL schemas are composed of resolvers and while I used active record in all of my examples that doesn't have to be the case the data can be resolved from absolutely anywhere which makes graph QL a facade it's a facade in front of your database cache and services and in this era of micro services that we found ourselves in you can tuck all of the complexities of an application behind this single simple interface and you get to use your own existing application code one of the biggest misconceptions that I hear about graph QL is I don't want to add a whole graph data store to my stack that's that sounds like a pain but that's not quite what we're doing we're building a query language on top of your existing application code and that's what we've done at github so github as a company is almost nine years old now the REST API that our users rely on what we call v3 has been in use of six of those last nine years and to be honest the API really hasn't changed that much we add new resources as new features are released but we strive to keep the least amount of change as possible because every time that we change our API were to use it we're doing our users a disservice that means that our users to update their code because it may be broken but as you can imagine there's some pain that comes with supporting a six year old API so about a year ago when we started discussing what the next version of our API could look like we all had ideas of improvements that we wanted to make but it wasn't until March 20th 2016 when the original proposal for graph QL at github was submitted that the next version of our API really started to take shape a few weeks later a proof-of-concept was done and it allowed us to query for things like repositories and users the the straightforward objects in github system and after seeing this proof of concept we all started asking each other if this is what we could do in a matter of weeks imagine what we could do over the course of say a year so about a week later a new team was created to take the proof-of-concept to and to the next level and see really how far that we could get from ql' and about eight months later where we released graph QL to the public at github universe it's a developer conference that we put on in San Francisco every year and it was an opportunity for us to get feedback from our users on this new API and fast forward to today we actually execute over a hundred million queries graph QL queries every day and we use graph QL both externally through a very similar endpoint to all of the examples that we saw today but we also use graph QL internally we use a gem called graph QL client which allows us to exchange a query for these nice pretty ruby objects so you can do things like restaurant name restaurant cuisine and what this allows us to do is co-locate our queries in our views and our rails views and for anyone who's familiar with react that's a pattern that you might be familiar with we've also invested a lot of time in tooling one particular gem that my colleague aren't Ariki in here in the audience today built is graph QL Docs and what that allows us to do is take the results of the instruments introspection query and put it all in this nice pretty HTML this is what builds the developer github.com website you can see that it showcases all of the types that we have all of the fields and it's awaited for us to show all of the descriptions that we've annotated inside of our schema we also practice something called schema driven development so before with our REST API new developed new features were developed for the UI first so take for example the project board feature was released about a year ago the way that that feature would have been built is we start with say the model then we move on to the controller and then we have our view until eventually we have this feature inside of the UI now after that we would staff ship it because we're github errs using github to build github we dog food the out of the application and so after we get feedback on all of the staff ship we might make it arisians on this feature and then we release it to the world and so it wasn't until after that release that work would start on the REST API but today all new features are built with graph QL from the start and what this this allows us to do is build a truly public API something that's in sync with our features as they're released but not only does this allow us to build just an API this allows us to build a true platform something that's shared between the product engineers at github and our users our integrators the people that are building on top of this API so going back to the question that I asked earlier what if we wanted to put our clients first well I believe the graph QL is one way that we can do that thank you [Applause]
Info
Channel: Coding Tech
Views: 235,859
Rating: 4.942029 out of 5
Keywords: qraphql, rest api, api, graphql api
Id: broQmxQAMjM
Channel Id: undefined
Length: 23min 40sec (1420 seconds)
Published: Tue Feb 27 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.