[RAILS] 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
Try using gRPC in Ruby
Sorting hashes 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
Class in Ruby
Heavy in Ruby! ??
Escape processing when creating a URL in Ruby
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
Create a native extension of Ruby in Rust
How to implement Pagination in GraphQL (for ruby)
Implement the algorithm in Ruby: Day 2 -Bubble sort-
Do something like a JS immediate function in Ruby
Count the number of occurrences of a string in Ruby
How to implement a like feature in Ajax in Rails
About eval in Ruby
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
What impressed me as a beginner in writing Ruby
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
Use Coveralls with GitHub Actions in a Ruby repository
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
In Ruby you can define a method with any name
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
Ruby Learning # 2 Drawing a Shape
Implement application function in Rails
ABC177 --solving E in Ruby
Validate JWT token in Ruby
Implemented XPath 1.0 parser in Ruby
What is a Ruby module?
Read design patterns in Ruby
GraphQL Client starting with Ruby