All right, so we refactored our JWT auth guard.
Let's do the same thing for our reservations service now.
So we'll go into our reservation service and this is going to follow a very similar pattern where currently
we're calling out to the payment service.
We're going to follow the same pattern we did in the auth guard to properly inject the payment service
in this reservation service.
So let's start off by making sure we implement on module init and then we'll declare this private payment
service of type payments, service client.
And now let's go ahead and change the injection token to be payment service name.
I'll change the name to be client and the type to be client gRPC from Nestjs Microservices.
Now, just as we've done before, we'll implement on module init and set this dot payment service equal
to this dot client dot get service.
I'll pass in the payment service client and we'll pass in the payments service name which we can see
is payment service.
Just a simple string which matches our proto definition.
So just as we did in the auth guard, instead of calling dot send, we're actually going to call the
method on the payment service, which will be create charge and we can get rid of the first argument.
We'll simply just include all of the arguments that the Create charge method expects.
Lastly, I'll go ahead and remove all of the unused imports and now our reservation service is properly
refactored to utilize gRPC.
All right, so it's time to actually configure our reservations module to set up gRPC and change from
TCP to gRPC in our clients module.
Let's go ahead and firstly change our transport to now be transport gRPC.
And then our options are going to change.
So instead of a host in port, we now need to specify the package that we want to connect to in our
gRPC proto definition.
So this is where we're going to use the auth package name constant exported from our OTS.
Thanks to TS Proto, the package will automatically be exported as a const for us.
Next up, we need to specify the proto path which is going to be the path to the proto file which our
application will use to actually run our gRPC server.
So to do this we're going to use the join function that we import from path up top.
And now let's specify the path to our proto file.
So the first argument will be the current directory name.
And then from here we're going to go up three directories into proto slash author Proto.
Now later on we're going to refactor our Docker file for our reservation service so that we actually
copy over the necessary protos and that this path will be actually available when our container is running.
Finally, we're going to specify a URL, which is going to be the URL to the actual auth service running
on gRPC.
So in our case we can actually get this from the config service.
We'll call, get or throw and then call auth grpc URL.
So now let's go into our M file for the reservations.
And now instead of the auth host and port, we can change this to be the auth underscore gRPC underscore
url and we'll set this equal to auth colon 5001.
So auth will be the name of our Docker container which we know we set in our Docker compose, which
is the host name of the container and the port here 5001 will be the default port that our gRPC server
will be running on in each of our containers.
So now we've correctly set up the auth service in the reservations module.
Let's go ahead and do the same exact thing for the payment service.
Now we'll change the transport to gRPC and let's go ahead and just copy the existing options we just
set up and we'll paste this in.
We just need to change the package name now to be the payments package name from App slash Common and
then the path of the Proto will now be the payments dot proto.
Finally, instead of the auth gRPC URL, we'll specify we want the payments gRPC URL and we'll add this
to our move and replace it just like we did before.
So now let's say that the payments gRPC URL will be equal to payments, which is the name of our Docker
container on Port 5001.
All right, so this is everything we have to do to configure our clients module.
Let's now go inside of the Docker file where we're going to add the appropriate line to actually copy
the proto from the root of our project.
So we need these proto copied over into our Docker container so that they're available during runtime.
So this is super easy to do.
We'll just run a copy command and copy from proto to proto.
So this is everything we have to do in the reservation service.
Let's now go into the payments service where we will now refactor this to be compatible with our gRPC
implementation.
So firstly, in the payment service, let's declare a new private notifications service of type notification
service client.
And we'll also go ahead and refactor our constructor so that we're injecting the notifications service
name from app slash common and we'll change the private read only client to a client gRPC from Nestjs
Microservices.
Next up, we need to refactor our call to create to the Stripe API.
So right now we're just supplying the card object from the payments crate charge DTO.
However, remember that we refactored this to be compatible with gRPC and actually changed expiration
month and expiration year to be camel case instead of using underscores.
So we need to map this back now in the service layer.
So I'm going to set the card equal to an object and explicitly set all the properties on the card from
the card itself.
So first we have the card CVC, and we have the number from the card number.
Now we're going to map the expiration underscore month to the card dot x month and x year said equal
to card dot x year.
So now we've properly mapped the DTO to what the Stripe API expects.
So next up, we need to actually set the notification service.
Now let's go ahead and do this directly in the method here.
We can check to see if the notification service is not set.
We'll go ahead and set it right now.
So let's set the notification service equal to this dot client dot, get service, pass in the notification
service client, and then we'll pass in the notification service name as the service that we want to
get using the gRPC client.
So now instead of emitting, which we cannot do with the gRPC client, we're directly going to call,
notify email on this method and get rid of the first parameter and keep everything else.
Additionally, this is still going to be a cold observable so that we need to actually subscribe to
the return type if we want this to actually get executed.
So let's go ahead and do that.
We'll subscribe directly to the observable and just leave an empty function so that our function here
still will get executed because we are subscribing to the observable.
Now, I set the notification service like this opposed to using on module net because I wanted to show
you that we can do this at runtime when the application is running and it doesn't always have to be
done in on module init like we've done before.
So finally we can go up to the top and remove some dependencies that we're no longer using.
Now let's go into the payments module where we will refactor the register async call as we did before.
So we're going to make sure we change the transport to be using gRPC and let's go ahead and change out
our options.
So firstly we'll have the proto path which will use Join again to help us out with finding the correct
file.
So we'll pass in the directory name as first argument.
And now let's go up three directories to proto slash notifications dot proto to find the correct proto.
Next for the package we're going to target the notifications package name from app slash common and
then the url we will use config service dot get or throw and ask for the notifications grpc url.
So let's go ahead and make sure we actually set this in our dot env.
So instead of the notifications host and port, we'll use the notifications gRPC url and set this equal
to notifications which is the name of our Docker container on port 5001.
Okay, so now in the payments controller, we're going to use the decorators provided by Proto, which
is going to make sure that Nestjs will know how to map incoming messages using gRPC to these actual
methods.
So previously we've utilized the message pattern decorator.
However, we can get rid of this and just utilize the proto decorators which we will add now.
So to do this we only need to add one decorator and that's going to be the payments service controller
methods and we can change this import to be from app slash common.
And now with just this one decorator Proto will automatically add all the necessary metadata to our
functions in here so that when the incoming message using gRPC comes into this controller, it will
go to this correct function and we can even get rid of the payload decorator here.
We don't need this because Proto will automatically be providing us with the correct arguments.
Now finally, to make sure that the controller is type safe and that we actually don't forget any methods
that are gRPC proto definition expects on this payments controller.
We can actually make sure we implement the payments service controller.
And now let's say for example, we forgot to implement create charge.
The payments controller would complain because the payment service controller makes sure we implement
everything defined in our proto definition.
In this case the create charge method.
So this will make our code type safe.
Now next up, let's go to our main.ts in the payments service where we're going to refactor the connect
microservice call.
So instead of TCP, now we're using gRPC and the options we're going to provide here are going to be
the same exact options we've already provided to the reservation module so we can simply copy these.
Let's go ahead and copy these and we'll paste them in to our current options object.
I'll import the payments package name and change this import to be from app slash common.
Make sure we import join.
And now we need to make sure we have the payments.
gRPC URL correctly configured.
So let's go ahead and add that payments.
gRPC URL equal to payments 5001.
Finally, let's go into our Docker file for payments and make sure we do just the same as we did for
the Reservations Docker file.
We need to copy over the proto from the root of our folder into our container so that it's available
during runtime.
Now let's also go into our notifications controller and follow the same pattern that we just implemented.
So we're going to decorate the notifications controller with the notifications, service controller
methods from app slash common.
So as we've seen before, this is going to make sure that all the correct metadata is added to these
methods.
Next up, we'll make sure that we are implementing the notification.
Service controller so that our code is type safe and that we can go ahead and get rid of the event pattern
decorator and remove the payload decorator as well.
Now, as I said before, we're still going to have validation on all of our methods in our microservices,
even though we're using gRPC.
Thanks to Class Validator and our validation pipe we're using here all of our pipes, interceptors,
middleware, everything will still work, just as it did before.
And our notify email DTO with the class validator decorators, we will still have validation applied.
Even though we're using gRPC, nothing will change.
So we can lastly go ahead and just remove these unused imports that we are no longer using.
And let's go into the Main.ts for notifications now and refactor the transport to be in gRPC.
And now we can go to the payments module and copy the options that are used currently to connect to
the notifications service.
And let's just paste these in here so that we are finding the proto for notifications and we are targeting
the notifications package name.
We can change this import to be from app slash common.
And finally in our Env, let's make sure that we have the notifications.
gRPC URL set equal to notifications 5001.
Now finally, don't forget in our Docker file, just as we've done before, we will copy the proto into
our current running container.
Now, one thing we want to add to our existing JWT strategy is actually adding an extra question mark
here on line 19 to check to see if there are headers being passed at all, because in our case with
gRPC, there are no headers.
So this will fail if we don't check to see if headers is defined first before accessing it.
Now that we've done that, let's go to our main.ts for auth and change the transport here to be gRPC.
As we've already done before.
And we can go back to the reservations module and copy all of these options and paste them in to the
options object here and simply import everything we need from app slash common to correctly configure
this gRPC microservice.
I'll make sure I import everything correctly and then we can replace the TCP port with the auth gRPC
URL, which we know will be auth 5001.
Next up, let's go into the auth controller where we will decorate this with the auth service controller
methods from app slash common.
We can also implement the auth service controller to make sure we're type safe and implementing all
of the gRPC methods that we expect to be.
And then we will refactor our authenticate methods so we can remove the existing message pattern and
we still want to pull the payload off of authenticate because by default we're not going to be supplied
this by Proto because it doesn't expect this to be coming in from our local strategy.
And now instead of returning the data dot user, we want to return an object where we spread everything
on the incoming user, which of course, if you remember, is being provided from our JWT strategy.
Now the only difference is we need to explicitly set the ID property here from the data dot user dot
underscore ID because gRPC will not allow underscores.
We need to make sure we're mapping the ID properly here when we're passing it over the wire.
Let's go ahead and remove all of our unused imports as well.
And then we'll go into the Docker file and copy over the proto definition so that auth has access to
them.
Now, since we've refactored to no longer require certain environment variables, let's go to our payments
dot module and remove the notifications, host and port as required environment variables as well as
the port itself, which we no longer are utilizing.
We'll go ahead and do the same thing in the reservations module.
We can get rid of all of the host and port environment variable validations that we're currently using
and let's go ahead and do the same thing in the auth dot module.
We'll get rid of the TCP port and in the notifications module we can also remove the port which we no
longer are utilizing.
Now, finally, we need to change the injection tokens that we're currently using instead of these injection
tokens that we've defined.
We're going to use the ones from TF Proto, which we are using inside of our services.
So for the auth service, this will be auth service name from app slash common and payments service
name from app slash common.
Now, finally, let's go ahead and change the injection token from notifications to notifications service
name, which is the injection token we're using inside of the payments service, which matches this
injection token we have in the constructor.
So now at this point, we're ready to go ahead and rebuild our containers.
So firstly I'm going to run NPM install dash R to recursively install all dependencies in our packages
to make sure we're up to date and then I'll run and end to run Docker, compose up dash dash build,
which is going to rebuild all of our containers and make sure we have the most up to date dependencies
provided to our containers.
So go ahead and let this command finish running.
Okay, so now I can see all of my microservices have started up successfully and we can test out our
functionality.
So open up postman and we'll firstly launch a post request at localhost 3001 slash users to firstly
create a new user with an email and password.
So I've created a new user and I will then launch a request at auth slash login to actually log in and
get our JWT set.
Next I'll launch a reservations request, a localhost 3000 slash reservations and send our typical payload
to create a new reservation.
I'll change the amount here to be $60 and send this off to create the reservation.
You can see we have a 201 created that has come back with the reservation.
And now if I go up to my browser and navigate to the Stripe dashboard, I'll go ahead and refresh.
You can see we have that $60 payment that has just come into the system.
So our payment service is working properly.
And if I go to my email I can see I have a payment of $60 that has completed successfully from Sleeper.
So our notifications microservice is also working properly.
So now we fully refactor our application to work with gRPC.