gRPC Golang | Persist User Data | Part 2

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up everybody my name is moss and welcome back to our tutorial series on grpc using the go programming language in the previous video we wrote a very simple unary grpc service method and in this video we're going to extend the functionality of our grpc user management service as you can imagine a user management service might give you the ability to create new users which is functionality that we already wrote but it might also provide functions to read existing user data update user data and delete users and what we'll do in this video is add a new grpc service method called get users when a client calls the get user service method the grpc server will return a list of active users so any user that was created using the create new user service method should be returned in a list when calling the git users service method by adding this service method to our user management service we'll learn how to do the following first we'll learn how to write nested proto messages and secondly we'll learn how to persist data between calls to our grpc service methods if you haven't already go ahead and grab a coffee and let's get started okay so the first thing that i want to do is modify the service definition in the user management proto file let's start by defining the service method signature so i'm going to go down here and i'll say rpc and then the name of the service method i'll call git users and the input for the get users service method will be an empty message called get users params and the reason that i'm using an empty message as the input for the git users service method is because in the initial implementation of the get user service method i simply want to return a list of all of the created users but in future iterations we may want to pass in parameters to the get user's service method for instance i might want to pass in a regular expression to the function that returns only a subset of users that match that regular expression pattern so in order to keep the api backwards compatible i'm going to pass in an empty message as the input and so this service method will return a list of users and will call that message a user list so now that we've defined the service method signature let's go ahead and define the input and output messages the first message will be easy to define if i scroll down uh to the bottom here i'll define a new message and we're going to call it get users params and this will be an empty message so we'll leave it just like that and let's go ahead and define the last and this message we'll call user list and inside of user lists we're going to use a keyword that we haven't seen before and it's called repeated so i'm going to say repeated and then user users equals 1. the repeated keyword is something that we use in order to return a list of something inside of a proto message so we can return a list of integers strings or in our case users so we're actually returning a list of the user message type using the repeated keyword after defining that last message we can go ahead and recompile our protobuf files so i'm going to rerun the proto c command that we used in the previous video and to do that i'm going to quickly save the file and then i'll use up arrow to search my shell history and i think that's the correct command so i'm going to go ahead and select enter and it looks like it successfully recompiled the protobuf files so now that our protobuf files have been recompiled we can begin modifying our user management server and user management client code to utilize the get users service method so let's first modify the user management server code so i'm going to go ahead and clear the terminal and navigate to the user management server dot go file and the first change that we're going to make is in the user management server type we're going to add a new attribute to this type so under the unimplemented user management server attribute we'll define a new variable and we'll call it user underscore list and it will be of type protobuf user list so it will be a user list struct which was automatically generated from the compilation of our proto definition and if i hover over it you can see that is it is an array of user user struct pointers or rather the user list struct contains an attribute called users and users is an array of user pointers so this userlist variable will be the in-memory data structure that we used to store users that were created when a client called the create new user grpc service method so now that we've defined the user list attribute let's go ahead and write a new function and this function is essentially going to be a constructor for the user management server type so i'm going to say func and then new user management server and it will return a pointer to a user management server and inside of this function we'll simply return the address to a user management server and inside of the user management server instantiation will set the user list attribute to a new protobuf user list so now that we have the constructor function defined let's write a new function that will simplify the execution of the main function so right now in the main function we set up a new grpc server we register that user management server and and then we call serv so let's move this code into its own function and we'll call that function run and it will be a receiver function of the user management server type so under the user management server definition let's write new function and it will receive a server which is a pointer to a user management server and we'll call this the run function and the run function will return an error okay and all we're going to do in this function is move the code that's in the main function into the run function so what i'm going to do is i'm going to scroll down to the main function and i'll just copy all of this here okay let's cut it and then paste that into the run function and what i'm going to do at the bottom of this function is simply return the result of the call to serve so here i'll just say return and then i'll delete everything else so now the run function and the constructor function simplify the code that we have to write in the main function so if i scroll down uh to the main function we really only need a couple lines of code in the main function the first is we're going to instantiate a new user management server so i'm going to call it user management server and it will be a pointer to user management server type and then we'll call our constructor function new user management server and then the second thing that we need to do is simply call the run function on the user management server that we just created so here i'll check for an error and call the run function so if error equal user management server dot run and error is not equal to nil we'll log fatal and we'll say failed to serve and that's all we need in the main function and now there's only two other things that we need to do here the first is in the create new user function so when the create new user function is called we should append any new users to the user management server user list so the first thing that i'll do in the create new user function is take the user definition that we have here and we're going to define a new variable and we'll call it created user and leave it like that and what we'll do is append the created user to the user management server user list so to do that i'm going to invoke our server so s dot user list dot users equals append uh s dot userlist.users as source and then created user okay and finally we'll return the created user so there's only one last thing to do and that's to implement the get users function so i'll define a new receiver function under the create new user function and it will receive s which is a pointer to user management server and we'll call it get users and git users will take as input a context and then it will also take a pointer to a protobuf get user params message and it will return a pointer to protobuf user list as well as an error and as you probably already guessed all we're going to do in this function is return s dot user list and nil and that wraps up all of the modifications that we need to make to the server code so i'm going to go ahead and open up the client code so we can begin modifying that and in the client code we really only need to call the get users service method and we'll do that after calling the create new user service method so i'll scroll down here below where we print the user details that are returned to us after calling the create new user service method and before calling the service method we'll first initialize an empty message as input to the call to get users so we'll call it params equal the address to protobuf.getuserparams and then immediately following that we'll call the git user get users service method so we'll define two variables r for the response and then error equals client dot get users we'll pass in context and then our empty params message and then after calling git users we will check for an error so if error is not equal to nil log fatal and then could not retrieve users otherwise we'll simply print the user list that we received from the server to the terminal so i'll say log.print newline user list and newline and then we'll do a formatted print statement so printf r dot get users new line and then we'll call r dot get users so this call to get users should return an array of users that are stored within the user management servers user list struct and we don't have to make any additional changes to the client code so let's go ahead and run the program and see what happens so in the terminal i'll first run the user management server so i'll say go run user management server okay and once that's running i will start a new terminal and we will run the client okay so go run user management client client and i got a really weird error here it says uh rpc error code unavailable descriptor so let's take a look at the output of the server and it looks like the server program actually terminated with a segmentation fault so that's not good and looking at the stack trace it's pointing to line 44 in the user management server code so let me navigate to line 44. on line 44 we're just appending uh the created user to the user list of the server of the user management server but i think i i might know where the issue is it's where we copy and pasted the code in the main function into the run function in the call to the register user management server the second parameter here shouldn't be the address to the user management server type it should actually be the server that is that the run function receives so i'm going to replace this parameter with server and i'll go ahead and save the file and let's try and run the server again i'll clear the terminal okay so the server's running and now let's run the client program and see if it works this time and it looks like it's working now you can see uh in the output uh here we're uh calling to create new user function first for bob and then for alice and then we call the get users function and that returns the user list which includes bob and alice so obviously having all of our users stored in an in-memory data structure isn't a scalable solution and we would want a more robust solution but implementing this solution showed us how we can persist in memory data between grpc service method calls and allow those service methods access to that data in future videos we'll explore more scalable solutions but i hope you enjoyed this video and if you did please consider throwing a like on the video and subscribing to the channel for more videos like this and as always the code that we wrote today is available in a github repository that i've linked in the video description below thanks for watching you
Info
Channel: Tech and Beyond With Moss
Views: 1,076
Rating: undefined out of 5
Keywords: golang tutorial, golang grpc tutorial, grpc golang, grpc tutorial, protobuf tutorial, go grpc server, learn golang, golang grpc, go microservices, microservices tutorial, protocol buffer, golang web development
Id: QmIdWTidEa8
Channel Id: undefined
Length: 16min 53sec (1013 seconds)
Published: Fri Jul 16 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.