Implement a gRPC client in Ruby

Write down the procedure for implementing the gRPC client in Ruby as a reminder.

First, insert the gem

--Install grpc gem to use gRPC with Ruby --By including this, you will be able to use the classes required for implementing the client.

gem 'grpc', '~> X.XX.X'

Getting and compiling .proto files

--There are several ways to manage .proto files, but see this article for details. --Use a Gem called grpc_tools to compile .proto into an rb file

$ gem install grpc-tools

--The compile command looks like the following

$ grpc_tools_ruby_protoc -I ./proto \--ruby_out=lib --grpc_out=lib ./proto/hoge_proto/*.proto

--Specify a directory to search for .proto files with the -I option --Specify the output destination directory after compilation with the --ruby_out option ――It's fine anywhere, but it seems that there are many / lib --In the first argument of the --grpc_out option, specify the output destination of the class file that will be the stub after compilation, and in the second argument, specify the directory containing the .proto file to be compiled. --If the compilation is successful, the pb.rb file corresponding to each proto and the hoge_services_pb.rb file that imports all of them and modularizes them are generated. --This hoge_services_pb.rb has the definition of rpc method and the definition of Stub, and this class will be used for calling.

Implementation of client stub

Now that the preparations are complete, we will actually implement it from here. First, create the stub instance needed to make the gRPC call. Regarding the creation of a stub instance, I often see the method of creating a file under / initializer and creating a new file there, but I didn't want to plunge into a global variable, so this time I cut the model class and apply the singleton pattern. Implemented in. To be honest, I'm still looking for best practices around here.

model/grpc/hoge_service_client.rb


require 'proto/hoge_services_pb'
require 'singleton'

#It is better to make this from the configuration file for each environment
END_POINT = "localhost:50051"

class Grpc::HogeServiceClient
  include Singleton

  attr_reader :stub

  def initialize
    @stub = HogeProto::HogeService::Stub.new(END_POINT, :this_channel_is_insecure)
  end
end

--For the Stub instance creation part, as mentioned above, the instance is created by creating a new Stub described in hoge_services_pb.rb. --The first argument of new specifies the gRPC server endpoint --The second argument is an argument for encryption during rpc communication, and if you want to operate it properly, you will need to specify the SSL certificate path, etc.

Actually call the gRPC server

Try to actually call rpc using the Stub created above

grpc/hoge.rb


class Grpc::Hoge
  def get_name(params)
    #Create an instance of model that has a Stub instance
    client = Grpc::HogeServiceClient.instance
    #Create request data required for rpc call
    req = get_name_request(params)
    #Create metadata if needed
    meta = Hash.new
    meta["x-app-id"] = "hogeghoge"
    meta["x-app-password"] = "fugafuga"

    begin
      #Here rpc call
      client.stub.get_name(req, {metadata: meta})
      res = "success"
    rescue GRPC::BadStatus => ex
      res = "error"
    rescue ex
      res = "unexpected error"
    end

    res
  end

  private

  def get_name_request(params)
    HogeProto::GetNameRequest.new(
      id: params[:id]
    )
  end

--You are calling rpc in the client.stub.get_name part --If the result of this call is an error (Status.Codes is not OK), an exception will occur, so enclose it in begin and rescue if it is an error. --For meta, the metadata is set at the time of gRPC call. --Here, the ID and password are set, but it seems better to initialize the common necessary items as instance variables on the model side that creates the stub. ――It seems that you can set the value in Hash format normally. --However, note that uppercase letters cannot be used for keys.

About error handling

As I mentioned earlier, when an rpc call returns an error status response, an exception of GRPC :: BadStatus class occurs. Therefore, it is necessary to always begin ~ rescue. Also, if the server side returns with error_details packed, it is necessary to implement to retrieve it. Reference: https://www.rubydoc.info/gems/grpc/GRPC/BadStatus

Recommended Posts

Implement a gRPC client in Ruby
Multiplication in a Ruby array
3 Implement a simple interpreter in Java
Try to implement Yubaba in Ruby
Implement a contact form in Rails
I tried a calendar problem in Ruby
[Ruby] I made a simple Ping client
Implement the algorithm in Ruby: Day 1 -Euclidean algorithm-
Implement something like a stack in Java
Tips for gRPC error handling in Ruby
Heavy in Ruby! ??
Escape processing when creating a URL in Ruby
Implement user management functions in a wizard format
Implement the algorithm in Ruby: Day 3 -Binary search-
I made a Ruby extension library in C
How to implement a like feature in Rails
Implement the algorithm in Ruby: Day 4-Linear search-
(Ruby on Rails6) Creating data in a table
How to implement Pagination in GraphQL (for ruby)
Implement the algorithm in Ruby: Day 2 -Bubble sort-
Implement a multi-column IN clause (column: condition = n: n) in DOMA.
Calculate the difference between numbers in a Ruby array
[Ruby / Rails] Set a unique (unique) value in the class
How to launch another command in a Ruby program
I made a Restful server and client in Spring.
Quickly implement a singleton with an enum in Java
Output triangle in Ruby
Implement CustomView in code
[Programming complete] §5 Create a review management app in Ruby
Variable type in ruby
Fast popcount in Ruby
Implement markdown in Rails
Update your Java knowledge by writing a gRPC server in Java (2)
Difficulties in building a Ruby on Rails environment (Windows 10) (SQLite3)
How to change a string in an array to a number in Ruby
Update your Java knowledge by writing a gRPC server in Java (1)
I searched for a web framework with Gem in Ruby
How to display a graph in Ruby on Rails (LazyHighChart)
I want to create a Parquet file even in Ruby
I tried to implement a buggy web application in Kotlin
I tried to make a client of RESAS-API in Java
Apply CSS to a specific View in Ruby on Rails
I wrote a C parser (like) using PEG in Ruby
Implement application function in Rails
ABC177 --solving E in Ruby
Validate JWT token in Ruby
[Ruby] Extracting a two-dimensional array
What is a Ruby module?
GraphQL Client starting with Ruby
Write class inheritance in Ruby
Creating a calendar using Ruby
Update Ruby in Unicorn environment
Implement LTI authentication in Rails
Integer unified into Integer in Ruby 2.4
[Ruby] Exception handling in functions
Use ruby variables in javascript.
Implement Basic authentication in Java
About regular expressions in Ruby
Implement math combinations in Java
Create a fortune using Ruby
2 Implement simple parsing in Java