Twirbet is a Sorbet-friendly Ruby library for the Twirp RPC framework.
Twirbet is available as a Ruby gem. To install it via Bundler, run:
bundle install twirbet
Twirbet does not provide code generation (yet).
You can use the Twirbet::Service
and Twirbet::Client
classes to implement
and call Twirp services.
Given a service defined in ping.proto
:
syntax = "proto3";
service PingService {
rpc Ping(PingRequest) returns (PingResponse);
}
message PingRequest {
string message = 1;
}
message PingResponse {
string message = 1;
}
Here's the corresponding Ruby code:
require "twirbet"
require_relative "ping_pb"
module PingService
module Handler
extend T::Sig
extend T::Helpers
interface!
sig { abstract.params(request: PingRequest).returns(PingResponse) }
def ping(request); end
end
class Service < Twirbet::Service
extend T::Sig
service "PingService"
rpc "Ping", PingRequest, PingResponse, ruby_method: :ping
sig { params(handler: Handler).void }
def initialize(handler)
super(handler)
end
end
class Client < Twirbet::Client
extend T::Sig
include Handler
service "PingService"
rpc "Ping", PingRequest, PingResponse, ruby_method: :ping
sig { override.params(request: PingRequest, headers: T::Hash[String, String]).returns(PingResponse) }
def ping(request, headers = {})
call("Ping", request, headers)
end
end
end
Once you have defined a service, you can implement it by creating a class that
includes the Handler
interface:
class PingHandler
include PingService::Handler
sig { override.params(request: PingRequest).returns(PingResponse) }
def ping(request)
PingResponse.new(message: "Pong: #{request.message}")
end
end
All services are valid Rack applications. You can use any Rack server to start a Twirp server.
handler = PingHandler.new
service = PingService::Service.new(handler)
run service
You can call a service using the client:
client = PingService::Client.new("http://localhost:8080")
response = client.ping(PingRequest.new(message: "Hello, world!"))
puts response.message # => "Pong: Hello, world!"
Twirbet uses the built-in Net::HTTP
library to make HTTP requests. You can use
a different HTTP library by implementing the Twirbet::Transport
interface and
passing it to the client constructor:
For example, Twirbet provides a Twirbet::Transports::FakeTransport
class that
can be used for testing:
require "twirbet/transports/fake_transport"
transport = Twirbet::Transports::FakeTransport.new
client = PingService::Client.new("http://localhost:8080", transport: transport)
response = client.ping(PingRequest.new(message: "Hello, world!"))
puts response.message # => ""