Async::GRPCGuidesGetting Started

Getting Started

This guide explains how to get started with Async::GRPC for building gRPC clients and servers.

Installation

Add the gem to your project:

$ bundle add async-grpc

You'll also need protocol-grpc and async-http:

$ bundle add protocol-grpc async-http

Core Concepts

async-grpc provides:

Client Usage

Creating a Client

require "async/grpc"
require "async/http/endpoint"

endpoint = Async::HTTP::Endpoint.parse("https://grpc.example.com")
http_client = Async::HTTP::Client.new(endpoint)
client = Async::GRPC::Client.new(http_client)

Using a Stub

Create a stub from an interface definition:

# Define the interface
class GreeterInterface < Protocol::GRPC::Interface
	rpc :SayHello, request_class: Hello::HelloRequest, response_class: Hello::HelloReply
end

# Create a stub
stub = client.stub(GreeterInterface, "hello.Greeter")

# Make RPC calls (accepts both snake_case and PascalCase)
response = stub.say_hello(Hello::HelloRequest.new(name: "World"))
# or
response = stub.SayHello(Hello::HelloRequest.new(name: "World"))

Streaming RPCs

# Server streaming
stub.server_streaming_call(request) do |response|
	puts response.value
end

# Client streaming
stub.client_streaming_call do |output|
	output.write(request1)
	output.write(request2)
end

# Bidirectional streaming
stub.bidirectional_streaming do |input, output|
	input.each do |request|
		output.write(process(request))
	end
end

Server Usage

Defining a Service

require "async/grpc/service"

# Define the interface
class GreeterInterface < Protocol::GRPC::Interface
	rpc :SayHello, request_class: Hello::HelloRequest, response_class: Hello::HelloReply
end

# Implement the service
class GreeterService < Async::GRPC::Service
	def say_hello(input, output, call)
		request = input.read
		reply = Hello::HelloReply.new(message: "Hello, #{request.name}!")
		output.write(reply)
	end
end

Registering Services

require "async/grpc/dispatcher_middleware"

dispatcher = Async::GRPC::DispatcherMiddleware.new

service = GreeterService.new(GreeterInterface, "hello.Greeter")
dispatcher.register("hello.Greeter", service)

Running a Server

require "async/http/server"
require "async/http/endpoint"

endpoint = Async::HTTP::Endpoint.parse("http://localhost:50051")
server = Async::HTTP::Server.for(endpoint, dispatcher)

Async do
	server.run
end

Complete Example

require "async"
require "async/grpc"
require "async/http/server"
require "async/http/endpoint"

# Define interface
class GreeterInterface < Protocol::GRPC::Interface
	rpc :SayHello, request_class: Hello::HelloRequest, response_class: Hello::HelloReply
end

# Implement service
class GreeterService < Async::GRPC::Service
	def say_hello(input, output, call)
		request = input.read
		reply = Hello::HelloReply.new(message: "Hello, #{request.name}!")
		output.write(reply)
	end
end

Async do
		# Setup server
	endpoint = Async::HTTP::Endpoint.parse("http://localhost:50051")
	dispatcher = Async::GRPC::DispatcherMiddleware.new
	dispatcher.register("hello.Greeter", GreeterService.new(GreeterInterface, "hello.Greeter"))
	server = Async::HTTP::Server.for(endpoint, dispatcher)
	
		# Setup client
	client_endpoint = Async::HTTP::Endpoint.parse("http://localhost:50051")
	http_client = Async::HTTP::Client.new(client_endpoint)
	client = Async::GRPC::Client.new(http_client)
	stub = client.stub(GreeterInterface, "hello.Greeter")
	
		# Make a call
	request = Hello::HelloRequest.new(name: "World")
	response = stub.say_hello(request)
	puts response.message  # => "Hello, World!"
	
	server.run
end