RQL Tutorial - Composing Microservices

node v8.17.0
version: 0.0.2
endpointsharetweet
RapidQL can be very useful when working with microservices. Often times when building applications & UIs with microservices, it is desired to combine data from multiple services . For example, imagine a microserviced blog platform. Such platform could have an "articles" microservice containing all the articles and the IDs of the users that created them, and a "users" microservice containg information about those users. When rendering the homepage for such blog platform, it would be necessary to pull all the articles, and for each article to also pull the corrosponding user profile from the users service - to show the user name / profile picture. Luckily, this is made very easy by using RapidQL. ------
For the purpose of this tutorial, we have created 2 sample (mock) services: Users: https://untitled-h84u6u6620ky.runkit.sh/users -> will return all users' profile https://untitled-h84u6u6620ky.runkit.sh/user/1 -> will return the profile for user with id 1 Articles: https://untitled-7i14nvq5c87q.runkit.sh/articles -> will return all articles https://untitled-7i14nvq5c87q.runkit.sh/article/1 -> will return the article with id 1 You can see the data returned by both services by posting the URLs bellow in the browser.
First and foremost, initialize RapidQL:
const RapidQL = require('rapidql'); const rql = new RapidQL({});
Further, create a "services" object that holds the addresses for all the microservices. This will make development more convinient:
const services = { USERS_SERVICE : "https://untitled-h84u6u6620ky.runkit.sh", ARTICLES_SERVICE: "https://untitled-7i14nvq5c87q.runkit.sh", HACKER_NEWS_API: "https://hacker-news.firebaseio.com/v0" };
Initially, we can use RapidQL to make a GET request to the articles service and get all the articles:
await rql.query(`{ articles:Http.get(url:'{{{ARTICLES_SERVICE}}}/articles'){ } }`,services);
As you can see, this makes the request to the service and returns all the data as it was recieved. However, let's say for the homepage we want to modify this data slightly: 1. We only need the date, title and authorId (the article content won't be shown on the homepage) 2. We want to cast the date into a JavaScript date object Both modifications can be made easily:
await rql.query(`{ articles:Http.get(url:'{{{ARTICLES_SERVICE}}}/articles'){ authorId, date(published), title } }`,services);
Now, for each article, let's make an additional request to the users service to get the name of the author based on his id. This request will be made within the result of the original request to the articles service, and will use the authorId property from that request to get the right user:
await rql.query(`{ articles:Http.get(url:'{{{ARTICLES_SERVICE}}}/articles'){ authorId, date(published), title, author:Http.get(url:'{{{USERS_SERVICE}}}/user/{{authorId}}'){ name } } }`,services);
As you can see - this request returns the combined data from both services! **BONUS**: Those with a sharp eye would have noticed each profile in the users service has an additional `hackerNewsUsername` proerty. That property represents a hacker news account user name. We can easily make an additional request, using that data, to the hacker news API, and get the users karma (score) and about section:
await rql.query(`{ articles:Http.get(url:'{{{ARTICLES_SERVICE}}}/articles'){ authorId, date(published), title, author:Http.get(url:'{{{USERS_SERVICE}}}/user/{{authorId}}'){ name, hackerNewsUsername, hackerNewsProfile:Http.get(url:'{{{HACKER_NEWS_API}}}/user/{{hackerNewsUsername}}.json'){ karma, ?about } } } }`,services);
Notice the question mark before the about propery in the hacker news request. This tells RapidQL that some users won't have an about property - and that's OK (it'll just be null). By default, RapidQL looks for all the specified properies, and fails if they don't exist. That way you can be sure that if a query went through, all the data you expect is going to be there.
Loading…

no comments

    sign in to comment