NestJS gRPC Microservices Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone today we're going to look at implementing grpc with nest.js and building microservices with it so if you're interested in learning more about grpc itself I'll leave a link in the description to this page grpc.io where we can learn more about grpc which is a performant remote procedural call framework that can run in any environment so it's a way to connect Services together across machines and allows us to simplify communication between Services because we only have to define the definition for the services once and then we can share this definition across our applications no matter what language or client we're using it's scalable performant and used by a lot of companies as we can see here so let's go ahead and jump in to see how we can integrate grpc with nest.js and build some microservices real quick before we get started if you'd like to dive even deeper with grpc and nest.js microservices be sure to check out my sjs microservices udemy course which will have a dedicated section just on grpc where we connect multiple microservices together it's a highly rated course that I think you'd get a lot out of so thank you so much if you've already checked it out and if you haven't I invite you to check it out so you can learn more about grpc and SGS all right let's jump right into the lecture all right let's go ahead and get started by initializing a new project on the command line using the nest CLI now as always I'll leave a link in the description to the GitHub repository which will contain the completed project so if you don't have the nest CLI installed we can run sudo npm install Dash G at nest.js CLI at latest to get the latest version so if you already have it and you want to be on the latest version of nest.js you can rerun this to also upgrade so now we'll run Nest new to generate a new project and I'll call this nest.js slash grpc then I'll go ahead and use pnpm as my package manager so now we can CD into the generated project and see our project has been generated I'll also go ahead and open this up in vs code so now you can see my project in vs code which is the default Nest project out of the box we of course have our default application with the main.ts file that's right now exposing an HTTP server on localhost 3000 we have a get route set up so let's go ahead and test this out to make sure that everything's working properly we can run pnpm run start Dev so this get route is simply returning a hello world text string and if we open up Postman now and launch a get request at the localhost 3000 we'd be able to send this off and see we can have our hello world response being sent back with a 200 so our server is up and running so now we want to add a new microservice that our application can talk to and to do this we're going to create a new authentication microservice that will host users and we will go ahead and generate this by converting our Nest project into a mono repo we can do this by using the nest CLI to run Nest generate app and we'll call it off so now this has gone ahead and restructured our project to be a mono repo so our app our existing nest.js grpc app with our one get route has been moved into this nest.js grpc folder and our newly added auth app has also been added which looks exactly the same with a default HTTP server listening on Port 3000 exposing that get route through these generated auth controller and off service so importantly this has updated the nest cli.json this file lists all of our applications in our project so you can see down here those are projects object that has both of the applications so the nest.js grpc and auth and where its files are located or described here this has automatically been updated for us from the nas CLI however I want to rename our nest.js grpc app because I want this to be the API Gateway so this API Gateway is going to receive all of the HTTP traffic in our app and it's going to proxy those calls onto the auth microservice using grpc Okay so let's go ahead and rename this I'll rename the directory to API Gateway and then in this file we can actually just use the find and replace so I'll search for nest.js grpc in this file and all files and I'll replace it with API Gateway I'll go ahead and replace all occurrences and now our code has been updated to use the API Gateway terminology let's quickly go to the package.json and just rename the name of our app because I still want to call it an sjs grpc and now back in the terminal we can run start Dev to start up the API Gateway application which is still our default application out of the box and then I can open up another terminal window so that I can CD into our project directory and in here I'll rerun pnpm Run start Dev but now I'll Target the other application the auth application to start up now of course this is going to clash because we're listening on we're trying to listen on Port 3000 so we will shut it down for now until we refactor this to use grpc okay so let's go into our auth application and start refactoring it to be able to return some data in our case we're going to work with a user's entity to start off we'll go ahead and remove the auth controller and off service as we're not going to be using these so we'll go into the auth module as well and make sure we get rid of these Imports that reference it and we can also update our controllers and providers array now we're going to use the nest CLI again to generate this new user's resource we're on Nest generate resource users then it's going to go ahead and ask which project we want to generate it to the API Gateway or auth will choose the auth project and then it's also going to ask which transport layer we're going to use in our case we can go down and select the microservice non-http and we will ask it yes to generate us crud entry points so now if we go back we can see in the auth module we have a user's module being imported and if we go ahead and take a look at the users module it's referencing the user's controller that was generated to be able to expose all of these crud entry points into the system so create read update and delete and so this is using the message pattern decorator from nest.js microservices which we haven't installed yet and in here we're referencing the user service which right now is just returning stop data for all these crud methods so in the user's controller you can see it's complaining because we haven't installed the nest.js microservices library yet which is used to actually expose these crud methods to Nest let's go ahead and do that now and add all the additional dependencies we're going to need to actually work with grpc in this microservice okay so as I mentioned we'll need to pnpm install save at an sjs microservices so nestros microservices is the abstraction layer around our communication between our microservices and makes it very easy to swap out different transport layers later on if we wanted to switch how our microservices communicate this Library encapsulates all of that then we need to install some supporting libraries for orgrpc itself so let's install at grpc slash grpc.js and then grpc slash Proto loader so these are dependencies that nest.js microservices will be using under the hood now finally we're going to install one last dependency called TS Dash Proto mts-broto is going to allow us to generate typescript code from our protobuf definitions that we're going to be creating later on which is essentially the shape of our data and services using grpc so this is going to save us a lot of time and make it very easy to integrate grpc with an sjs so now if we go back to the user's controller you can see our dependencies are no longer missing and we can even go back to the terminal and start up the off server after stopping our other server and you can see it starts up fine so now we're ready to start actually building the protocol buffer definition that our grpc server will be using to understand the shape of our data and the methods that can act on it we're also going to use this Proto file to generate our typescript types for our entities in our application so let's go ahead and get started by creating a new Proto folder at the root of our project that's going to list all of our Proto definitions in our case we'll start off with the auth dot Proto which is going to be the definition for the off microservice that we have created now the first thing we will declare in our protophile is the syntax we're using there's different versions of Proto that we can use and the syntax will change depending on the version so we specify we're using proto3 which is the current version right now and you can notice I have syntax highlighting already in vs code and that's because I've installed the Proto extension so if you don't have you can install this one vs code proto3 to get vs code intellisense support and next we're going to declare the package name so in our case this is auth and notice we're ending each of these lines with a semicolon as well okay so now we're going to define the shape of our user entity so to do this we use the message keyword which just defines a new type essentially so we'll call this user and then open up an object of properties here where we can now enter in the properties that grpc will understand exists on this entity so the first one we will have is a string and if you start typing here you can see we actually pick up all the different types so we're going to use a string of ID and then we set it equal to one so all the properties on a message have to be numbered like this to represent the order of them next up we'll have a username and we'll set this equal to two string password and this will be three now we'll have an in 32 age set to four and then I also want a Boolean called subscribed see if the user is subscribed or not and then finally I want to show you that we can reference other message types by following this pattern so we can have a new message that we'll say called social media and in here I want to have two properties that will be actually optional so to specify optional properties we can use optional keyword and we'll have a string we'll call this Twitter URI set it equal to one so notice since this is a new message The Ordering of the properties has to restart as well and we'll have another optional string of Facebook URI and set this equal to two and so now we can actually reference the social media message just by giving its type here and then we'll call it the social media and set it equal to six so now that we have the shape of our user defined we can actually start describing the service the user service itself and all of the methods that will be exposed so that our callers can end up calling these as remote procedural calls so let's go ahead and Define this new service called user service where we Define all of these RPC methods so to actually describe one of these we title it with RPC so remote procedural call create user will be our first one so this is essentially defining a function stub so we can Define parameters that it's going to take as well so in our case we'll have a new type called crate user dto and we've then we specified the returns keyword to specify what we're returning from the method so this case will return to user and we can enter curly brackets there so now this is the definition for the RPC create user call that callers can call and get a user back after they've created it so we need to Define this create user dto let's go ahead and do that now so we'll have a new message called create user dto with a string username set 1 string password set to 2. and then in 32 age set to 3. we will default the rest of these properties so when a user is being created these are the only properties we want to accept all right so following along with the rest of the crud methods in our users controller we'll now move on to finding all users so that we can find all the users in the system so let's define a new RPC find all users and for the parameter we want to Define in a new MD message type because by default we don't want to accept any information when we find all users so we can just describe that with an empty message type that we'll call empty so then we can Define that we take in an empty message as a parameter and we want to return an array of users now so to Define an array return type we still need to wrap it in an object so let's go ahead and Define a new message that explicitly will return an array of users so we'll call this message the users type and now we can Define the user's property on this object which will be the actual array of users so to specify this will be an array we can use the repeated keyword and then we say this is repeated user call it users instead of equal to one so this is referencing our user type but it's being repeated as well so now we can actually specify the return type of users in our our PC call next up we are going to implement find one user so we wanted to implement a new find one user dto let's do that with the find one user dto message type will create and this message will just take in a string of the ID so we can find one user by their ID and then we'll specify this type as the parameter which will return a single user all right so next up we have the RPC update user which will take in an update user dtl that we can Define so the update user GTO is going to be a subset of the properties on our user we will allow the ID to be passed because we need to be able to find the user we want to update and then we can say the social media property on the user can be updated using this method so now we can go ahead and specify that we will return a user back to the caller after we update that user and finally we have the RPC remove user which will take in a find one user dto to actually find the user that we're going to remove and then we can return the user we just deleted back to the caller so now we have a full RPC definition of the user service which tells our grpc clients which methods we can actually call on the server we have one place where we have all of the parameters and return types which is super useful because this protofile can freely be shared amongst many different applications and you have one place where you know the contract between the client and the server so finally I want to implement one more RPC call that's actually going to deal with streams which are long-term Live Connections in grpc which is super useful when you're trying to transfer a large amount of data and you don't want to do it all in one go but you can chunk it or if you have some sort of real-time application where data is being transferred between them very rapidly these long-lived connections can be super useful so I'll go ahead and show you how we can do this in sjs but we need to Define this RPC method that we'll call query users so this will represent some sort of large query of the users that we want to chunk back to the calling client and not send it all in one request so to do this we can specify this stream keyword which is taken a stream and then I want to define a new message type called pagination dto so the pagination dto is going to allow us to page between the users that we want to get back from the server so we'll have two properties the n32 page which specifies the current page we want and then in the int 32 skip which is going to be how many users we want to skip from the call so we can combine these properties to implement pagination and large data sets that we want to stream back so let's go ahead and reference this with the pagination dto and then we're going to return a stream of users back to the client so this is going to implement a two-way connection between the client and server because we're returning a stream and we're also taking in a stream we do have one small fix we need to make on our update User dto make sure the social media property here is lowercase social media to match our existing user model okay so now we're going to use the TS Proto package that we installed earlier to actually be able to generate typescript code from this Proto definition which is going to save us a bunch of time and make it very easy to keep our code and Proto up to date so to do this we're going to run this command up above here Proto C plugin equals and then we're going to Target the node modules folder slash bin slash Proto C gen TS underscore Proto so this is going to execute the script and then we have a TS Proto out option so we'll just generate it to the root and then we're going to add dash dash TS underscore Proto underscore opt equals Nest JS true which is going to generate code specifically for nest.js and then we provide the path to the Proto so our case is produce slash auth.proto which is where our proto-definition lives and now if we go back to the Proto folder we can see we have this new auth.ts file that was generated which is all of the typescript code from our Proto so we have the interface for the user the dtos and even methods that are controllers and clients are going to implement which is going to make it super easy to keep our code up to date so now that we have this generated type we want to move it into our applications so we can actually reference it so let's go back to the CLI and create a new common Library there are applications can utilize so we can share code easily and maintainably so I'll run Nest generate lib and call it common which will be our common Library we'll just use the default prefix and now our Nest cli.json was updated with this new common Library which is hosted under the libs common folder so by default it generates these common files I'm actually going to go ahead and delete all of them since we're not going to be using them and then in the source folder I'm going to add a new folder called types where we'll keep all of these generated types so then I'll move the auth type definition into the types folder now I'll create an index.ts in that types folder where I'll export everything from the auth type and then go back to the root index.ts in the common source folder we'll get rid of the existing exports and Export everything from the types directory so these types will be freely available to all applications so now that we have this generated type we can actually refactor our auth microservice to utilize it and become a true grpc microservice now before we do that we need to refactor our Nest cli.json a little bit so we need to modify it so that it actually copies over our Proto definition folder here at the source of our project into the out project in the disk directory so to do this we'll go into the project section and for auth we'll go ahead and change the source route to be at the root of our project instead of being in auth directly we then specify the entries in Source slash main and now in the compiler options we're going to go ahead and specify an assets array where we'll go ahead and specify that we want to copy over everything from the Roto slash star.proto folder so that it copies over all of our Proto definitions and then we'll have the watch assets set to true so that if there's any change to these Proto files that they will be copied over so let's go ahead and do the same thing for the API Gateway we'll have a source root at the root of our project and then we need to modify the entry file to be in Source slash main we'll also go ahead and copy over this compiler options from the auth microservice we can paste this in so that we copy over the Proto files and finally we need to do the same at the root of our definition in our Nest CLI so we'll change the source root to be at the root of our project and then add a new entry file where we specify source main is our entry file so now if we run p and PM Run start Dev auth and start up our development server we can go into the dist folder and if we open up the apps folder in auth we can see the Proto has been copied over so now we can utilize it in our running applications which we will need to do when we start up our microservices okay so now that we have the Proto available in our compiled app let's go back to the auth main.ts and refactor this to start actually using grpc so I'll go ahead and get rid of everything in the bootstrap function and create a new app set equal to a weight Nest Factory dot create microservice and then we'll pass in the micro service options and open up a function call where we can now provide the actual auth module which is our application Root module and then we have the options object for this microservice so in our case we'll specify the transport to be transport.grpc so this is what I said earlier where an sjs is going to encapsulate all of our microservice communication and then we can choose our transport option here out of all of the available ones we're going to use grpc and now open up an options object where we have to specify the Proto path which is going to be the path to our Proto definition for this service so to get access to this we'll use the join function from path so import this from path and then we'll use the underscore directory name so that we're in our current directory and then go up a directory to auths.proto which if you recall will be right outside of our source directory in our compiled app next we need to specify the name of the package that we're targeting so we're going to be using this on the server side and the client so I want to make this common code in our common Library so in a common Library I'll create a new folder called constants and then we can create a new packages dot TS file where I'll go ahead and export const auth and set equal to auth we'll also have to create another index.ts where we export everything from packages and then we'll update our root export to export everything from constants so this is where we can host all of our package names and share them between our client and server instead of having to duplicate that so let's go ahead and get access to auth and you can see by default it's going to use this import however I want to change this to reference app slash common which will be the Alias and allow us to freely swap out this path later on and not have to refactor all these Imports so now we have this microservice app we'll call awaitapp.listen so our microservice will start up and in our terminal we can see that the nest microservice successfully started so now back in our users folder in the auth project let's go ahead and actually delete the existing dto and entities folders since we have all of our common types in our common Library we don't need these types anymore and now it's time to actually refactor our users controller okay so now in our users controller we can actually refactor this to work with grpc and take advantage of the generated types from the TS Proto Library so we're going to utilize The Nest JS integration of it and actually implement using the implements keyword the user's service controller from app slash common so we'll go ahead and swap out our import and we'll remove these Imports to our existing dtos and change them to be from App slash common so we'll add both of those dtos and now we're implementing this user service controller so if we look at it now this is the service definition from our Proto definition which will ensure that our code is always properly implementing the proto-definition now finally we're also going to decorate this with the users service controller methods and what this is going to do is it's going to go through all of the methods in our users controller and properly decorate them with the grpc decorators from nest.js so we don't have to worry about any of the underlying configuration for these routes we just need to make sure that we implement this controller and TS Proto will take care of it for us so let's go ahead and get started we can actually remove the message pattern decorator as I mentioned because TS Proto is going to be decorating all of these methods for us with the proper metadata and now of course you can see our compiler is complaining because we are not implementing the correct methods that correspond to the interface and all of these methods map to our proto-definition now it's important the name is the same because that's how the nest.jsgrpc functionality will find out where these messages need to go to so let's go ahead and update this with the create username instead and we don't need to decorate this with the payload decorator because TS Proto is going to be providing this parameter for us and you can see the method is complaining because we are currently returning just string sub data and it expects a user to be returned which is great to see that it is type checking us let's go ahead and finish updating the rest of the methods in here so find all users and then for find one this will be find one user we'll get rid of the payload decorator and now we'll take in the find one user dto and we can import the find one user dto from App slash common and we will pass in the find one user.dto.id to our method next we have the update method which will take in the update user dto of type update user dto and we don't need to worry about the compiler complaining about the ID we will refactor this so let's change the name of this as well to update user and then finally we have remove user that will take in the find one user dto of type find one user dto and you can remind yourself of the types of these if you just go back to the type definition we can see which dto is being passed in and finally we'll pass in the find one user.dto.id now lastly we have the query users method which you can see I've Auto completed here I'll change this to be the pagination dto stream which will be of type observable pagination dto I'll get rid of the return type here as well and now we'll call return list.userservice dot query users and pass in the current pagination dto stream so I'll remove the unused import from our Imports section and now we can go into our user service and properly refactor this to implement crud functionality so let's go ahead and Define a new private read-only users property and here which will be our in-memory array of all the users in the system we'll import user from App slash common and also update the dto Imports to come from here as well so we can remove these so this will be a user array that will set equal to an empty array now I want to also implement on module and knit from sjs common so now we can Implement a bootstrap hook called on module init that nest.js will call every time our app starts up so every time our app starts up I'm going to want to create some new users so firstly let's go fill out the create method so we can create new users we're going to create a new user const here which will be of type user and let's spread all of the create user dto that's coming into the system and then we'll set these default properties that we know we need to set so this will be subscribed to false social media will set equal to an empty object and for the ID I'll use random uuid from the crypto Library so now I'm going to push the newly created user to the user's array and then we will return the user back to the caller I want to create a bunch of users that we can have as dummyc data so let's create a simple Loop that starts at zero and will iterate up to a hundred and in this loop we're just going to call this dot create and pass in a random username so I'll call random uuid again to have a random username and we'll do the same thing for password and I'll set an age here of zero so we have this randomly created user set being created on Startup next and find all we'll go ahead and return the user's dto which if you remember is an object that has the users set equal to this dot users which will be our array of users and we can go ahead and update our return types to make this more explicit so I'll use the user's type here and for create we'll also return this user type for find one I will return a user and now we'll take an ID if type string and we will return this dot users dot find so we have a user and we want to match the user dot ID up to the ID that's being passed in and find that particular user so next up for update we'll take in the ID of type string and we will return a user that has been updated so firstly we'll need to get access to the user index that we want to update so let's create a new user index const that will be equal to this dot users dot find index and we will look for the user.id equal to the ID that's being passed in so this will allow us to find the index of the user we want to update then we check to see if the user index does not equal negative one because find index we can see if it doesn't find the element we're looking for we'll return negative one so if the user index doesn't equal negative one it means we found the user to update so we will update our users array at the index of the user we want to update and set it equal to a new object where we'll go ahead and copy the existing user so we can access that by calling this dot users user index and then we'll add all of the update user dto properties on top of that so that we can update the user in our users array and finally we can return the user back to the caller by calling this dot users user index to get access to that user now if we didn't find the user to update we can throw a new not found exception and say user not found by ID and passing a template literal so we can pass in the ID and change this out for backticks here so now that we can send the correct message that we didn't find the user next up we have the removed method which will take the ID of type string so this will be quite similar to update we first need to find the user that we want to remove so let's look for the user index again we can just copy over this existing logic to find the user by index and then we'll check to see if the user index does not equal negative one so the user was found we will return this dot users dot splice which will allow us to remove an element from an array at a specified index so the user index will be where we want to remove and then we will return at element zero because splice will return a array of the removed elements we know there will just be one of them so we'll return that removed user we can also check to see if the user index was negative one it was not found we'll throw another not found exception okay lastly we have to implement the query users function so let's define the query users function that's going to take in that pagination dto stream up type observable pagination dto and this is going to return an observable of users so next we're going to set up a new subject from rxjs which will essentially be our reference to the stream that we are returning and allow us to attach functionality to both when the caller calls this stream and when it completes so let's go ahead and start by defining the subject called subject which will be equal to new subject from rxjs so in our case we can specify the users type here which will be a subsection of the users so this query user's function is essentially going to be paginating through our users array so you can imagine if it was thousands and thousands of users long and we don't want to return this massive array back in one go because it might take up so much memory that it could crash or application instead we want to stream the response back to the client so we're chunking a bit of users back over time so that's what our query users function will be doing with this subject let's go ahead and Define an on next function which is essentially what is going to happen when the caller requests more data so in this function we'll get past the pagination dto and we have a function that will essentially find the next subset of users that we want to return back to the caller based on the page we're on so to find the starting point of the request right now we're going to multiply the pagination dto.page by the pagination dto.skip so let's say if we're on page three and we skip 10 elements we'll be starting on the 30th element calling subject dot next where we specify the user's property is going to be equal to this dot users dot slice so slice is going to allow us to copy a subset of an array so we want to start at the start element that we found and we want to go from the start plus the pagination dto dot skip so we're essentially getting little pieces of this data set and building that over time so next we'll Define an oncomplete method so if there's some functionality you want it to do when the caller said I'm all done with the data you can do that here such as closing connections to a database or any other async functionality you can do that we'll call subject dot complete on on complete and now we can call pagination dto stream dot subscribe so we're actually subscribing to this stream from our client caller and then we can specify the next property which is going to be our on next function that we just implemented and then we have the complete function which we call oncomplete finally we need to return the subject back to the caller in our controller so we'll return subject dot as observable so our Nest microservice is still up and running okay with no compilation errors so now that we have implemented our users controller properly to be able to implement the grpc methods we've defined we need to actually expose these methods so that we can call them from a rest API and that's exactly what our API Gateway is going to do it's going to expose an HTTP server where we can call our auth microservice using grpc so let's go ahead and do just that by going back to our terminal and running Nest generate resource users again however this time we're going to generate it to the API Gateway and we're going to use the rest API transport layer and select yes to generate crud entry points now because we modified our Nest CLI to say that our source root is at the root of our project we want to make sure we move the users folder into API Gateway source so that we have the users folder here and then we can go ahead and update our app.module and add the users module from our local users folder and we can also get rid of the app service and app controller because we're not going to be using these so I'll go ahead and just delete them all together so now in the user's folder we can see we have the boilerplate crowd functionality exposed through this rest API let's go ahead and delete the dto and entities folders because we know we're going to be using the common user entity that we've already created in our common Library I'll go ahead and change the import in our controller now to be at app slash common and also make sure we import the update user dto as well so you can see all of our crud methods here that we're going to proxy off to our off microservice so now in the user service let's go ahead and implement this proxy first in the user's module we need to set up the connection to the off microservice and to do that in the Imports array we'll import the clients module from nastgs microservices and call register on it here we'll take an array of microservices that we want to communicate to the first one will be the auth service so we give it a name which will be the injection token that we can use later on in the user service to get access to this client module let's go ahead and create a new constants dot TS file here where we can export this const called auth service and this will just be called auth so now in the users module we can reference this constant value of the auth service and then we specify the transport of course is a transport.grpc and then this options object where we need to specify the package name we want to connect to and for the package name we can actually use the auth package name which will import from App slash common and this is actually coming from the generated type so previously we had to do this manually by creating our own packages let's go ahead and actually remove this now because we can reference the generated type and I'll also update to index.ts to remove the import from Constance and now we'll just rely on the generated type for our package name so this also means we need to go back to the main.ts in the auth service and make sure we import the auth package name here as well so now back in the users module we're referencing the auth package correctly now we'll specify the Proto path which will be the same as we did in the main.ts previously we will join the current directory name and go up one directory to the auth protophile so now we've done everything we need to actually get access to this client module so let's go into the user service where we can finally inject it we'll also go ahead and change our import to the dtos to be from App slash common and we'll add the update user dto as well and now we're going to go ahead and firstly Implement on module and net just like we've done before and now we'll declare a private user's service which is going to be equal to users service client from App slash common and of course this comes from our generated type where we can have this interface for the client that's calling the remote RPC service and you can see here we have the interface for our client which is exactly what we want in this user service where we're calling it so now in the Constructor we will use the add inject decorator from sjs common and enter in the auth service constant and now we will call it Private Client of type client grpc from Nest Js microservices now let's go ahead and Implement on module init where we'll set this dot user service equal to this.client.getservice and now we'll pass in a type of user service client and then we pass in the users service name from App slash common which as you might assume is also exported from our common type from TS Proto although we have this user service let's Implement these crud methods by proxying off our calls to the auth microservice so now it's going to be super simple we can just call this dot user service dot create user and pass in the create user dto essentially just proxying off this request so this is going to return an observable with the user inside of it and as we know in nest.js when we return an observable and then we return it from the calling controller and sjs will automatically subscribe to the observable and return the value within so we will return the user from this RPC call we'll go ahead and change find all to be this dot userservice dot find all users and pass in that empty dto for find one we'll change the ID out to be a string and then call this.userservice Dot find one user pass in the ID and now for update we'll call this dot userservice dot update user find the user by ID and then spread the update user dto to get all of the updated properties don't forget to also change the type here to be a string now finally for remove we'll change the ID to string and then we'll simply call this dot user service dot remove user and pass in the ID okay so next up I want to implement a method that will utilize our query users grpc stream call now in our case in our example I'm going to have some functionality that's going to reach out to the auth microservice get each chunk of users and let's say we want to send an email out to each of these users so of course we need to First retrieve these users in chunks because we don't want to return all of the users in once and overload our server instead we want to receive little chunks of users each page and then email the users in each page that we get back from the auth microservice using a stream so let's go ahead and implement this email users method that will first get a new variable called users with a dollar sign to represent that it will be a subject and we're going to set it equal to a new replay subject which is going to be our observable that we're passing to the auth microservice and the observable that we actually call next on so let's go ahead and do this so let's say when we first reach out to the off service we would send a request to say how many users we have so we count how many users we have and then we'll know how many pages we need to ask for so in our case we already know that there's going to be a hundred users so let's create four different calls here where we call next each time on the list of users and start off with page zero and you just skip of 25 so we'll get back 25 users in each chunk here so in total will add up to 100 users we just need to increment the page number for each call and then we'll call users.complete to say that the observable has been completed and now I want to call this Dot userservice.queryusers and then pass in our replay subject and now I want to subscribe to this call where we get the users back or the chunk of users back and then we can simply log out the chunk so we'll say chunk and to keep track of our current chunk number we can actually even set a chunk number here I'll set it equal to 1 to start and then in our console long statement we can log the chunk number and let's increment the chunk number after we log it out and then we'll also make sure we log the users themselves out here so now we can also see the users is complaining because we need to provide a type to the replay subject here and say that we're using a pagination dto to query the users so now back in the user's controller we'll expose a new endpoint to actually be able to act on this email users method so we'll have a new post method called email and we'll call this email users which will take in no parameters we'll simply return this dot user service dot email users all right so now we're ready to test out our API Gateway and grpc microservice so in one terminal I'll run start Dev API Gateway to start up our API Gateway and then in the other terminal I'll run pnpm run start Dev off to start up our auth microservice you can see the microservice starts up as well as our Epi Gateway here that has mapped the user's routes okay so I've opened up Postman and will launch a get request at low cost 3000 slash users and if we launch this off we can see we get this array of users sent back from our auth microservice using grpc from the gateway to auth and we have this auto-generated array of users that we created on Startup so we can see the communication between the microservices is working properly next we can go ahead and try creating a new user by launching a post request and now in the body we'll set an email so I'll give an email of test at test.com and it'll provide just any password here to create a new user we can see we have the user created and the response comes back as we'd expect we can take the ID of this created user and enter it in as part of the get request to get this single user and then let's try updating the users so we'll change the request to a patch and then we'll swap out the body to include the ID and now we'll add the social media property where we can specify an object and give a Facebook URI of tests to make sure this works properly so now we can see our user did get updated and we can see our social media property finally we can launch a delete request to delete this user and now if we try to get it back we should have an error thrown because the user no longer exists lastly let's try out our email method using streaming so if I launch a post request at users slash email you can see we have a 201 sent back and then if we look at the logs for our application in the API Gateway we can see a bunch of logs logging out all of the users but what I'm interested is looking at the chunk log so if we look we can see we're logging four times for each chunk that we're getting back and each time is a different set of users in this massive list of users so when we got back each Chunk we would go ahead and email or do whatever operation we need to do on this small sub of data and then move on to the next one so this way we're never overloading the system with massive amounts of data if this is coming from a database we can just work with small amounts of data using grpc streaming so I hope this video was helpful for you to show you how we can easily integrate grpc with nas Js being able to declare all of our types and methods on our data in one place in this protophile is super useful in my opinion because we can share this between any number of clients and not have to reduplicate all of these types which is great thanks so much for watching and I'll see you in the next one
Info
Channel: Michael Guay
Views: 23,745
Rating: undefined out of 5
Keywords:
Id: UkWcjVWs2UQ
Channel Id: undefined
Length: 55min 4sec (3304 seconds)
Published: Sun Jul 30 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.