Avoid N+1 Problem In Graphql Federation With GO (Part 2)
In the previous tutorial we have manage to set everything up including the code logic, our test case is simple which just involves 2 services: post service and the user service in one gateway. Previously, we haven’t try our code. So let’s try it now.
We have created the “launch.json” file under .vscode directory in both service. Now , Hit the “F5” in your keyboard and the “launch.json” file will execute the entrypoint of your project which is the server.go and also the .env file.
Both service is now running and you can access it in: localhost:8080 and localhost:8081 in your browser. You will find graphql playground for both service like below:
In the user service playground you will find the appearence exactly like above image.
Now that both services are running seperately, but before we go to the federation. Let’s create some data for the users and posts.
Now that we have one user in our database. Lets say, this user is going to create many Posts for himself. Later we also want to get all of the posts created by this users. Let’s now go to the posts service and create a few posts for this user.
I have created 2 Posts for this user. But, now that they are in separate service and a very bad data shape. At this moment, the gateway and graphql federation will help use merge and manager the services.
Now that I’m going to teach you how to write a good federation. Our final purpose is that the schema will return json format like below.
If you pay attention, this way the posts created is grouped based on the user who created it. But now, The user and post schema are in different service. Let’s join them together.
Now look at above image, we are going to define a type User in the post service. Here, we are not actually define a new type User in the post service, we are using the “@extends” directive that will later tell the gateway , that this type schema is actually belong to other service. So, The gateway will later search for the corresponding schema which match the defined schema in post service.
references: https://www.apollographql.com/docs/federation/#concern-based-separation
You can read more about this in the documentation.
Now, let’s run
go generate ./...
After running it, you will get changes in your schema.resolver.go file and also the entity.resolver.go file.
Let’s implement it now, in the schema.resolver.go, just provide the function that we have previously create which called “PostGetByUserID” from the package service , also do not forget to pass in the nessessary parameter to the function.
And now the schema.resolver.go file will look like below.
So, what we are doing here is that, all posts under this user will only be the post created by this user only. Actually this is not a best practice, why?, because this structure will cause N+1 problem which mean that everytime we do a query to database to SELECT all available users, this action will trigger the Posts resolver function to be called N times as much as the amount of users returned from the query. We can prevent this by using the gqlgen dataloaders. So, it won’t trigger the N+1 problem. But I will talk about it in the part 3 of this topic.
From now, let’s keep it this way and focus on the federation. But in the end of this tutorial, the repository of this project will implement the dataloader concept together with federation. So don’t worry.
in the entity.resolver.go , you will see that gqlgen generate a resolver name “FindUserByID”, but we actually do not have the logic function to support this resolver, so let’s just return User model as desired by the resolver , and pass ini whatever argument we have. In this case is id.
Let’s implement the gateway.
The gateway is built with nodejs. So, just simply init an NPM project, and install the following dependencies.
npm install @apollo-gateway apollo-server graphql
Now, everything is set, and we have done implementing the graphql federation. Let’s try it out. Start both services with “F5” on your keyboard, and after both services is running in port 8080 and port 8081, it’s now time for use to start the gateway we have built previously. And the magic happens here.
In the gateway directory , start the gateway.js file with node command
node gateway.js
The gateway will load all the schema from the currently running services we have listed in the gateway.
We tell the gateway that , there are 2 services, running in localhost on port 8080 and 8081, the gateway will load the services and also handle the federation we have made to the service.
Now, we can open the playground in port 4000, and you will see both user and post service are merged into one single playground, included the federated schema. How cool is it ?.
Let’s do some query
We have managed Implement graphql federation in the best pratice, and build a microservice architecture :)
If everything is set with the federation, let’s now proceed to the part 3 of the tutorial and combine dataloaders with federation to avoid N+1 problem.
link : https://medium.com/@louisaldorio/avoid-n-1-problem-in-graphql-federation-with-go-part-3-b580cb78f7e5
Github Repository: https://github.com/LouisAldorio/medium-graphql-federation