Using Thrift with Ruby

Ruby bindings for the Apache Thrift RPC system. The gem contains the runtime types, transports, protocols, and servers used by generated Ruby code for both clients and services.

Compatibility

Installation

Generating Ruby Code

The Ruby library does not include the Thrift compiler. Use a compiler built from the root of this repository to generate Ruby bindings:

thrift --gen rb path/to/service.thrift
# with namespaced modules
thrift --gen rb:namespaced --recurse path/to/service.thrift

Generated files are typically written to gen-rb/ and can be required directly from your application.

Basic Client Usage

$:.push File.expand_path('gen-rb', __dir__)
require 'thrift'
require 'calculator'

socket     = Thrift::Socket.new('localhost', 9090)
transport  = Thrift::BufferedTransport.new(socket)
protocol   = Thrift::BinaryProtocol.new(transport)
client     = Calculator::Client.new(protocol)

transport.open
puts client.add(1, 1)
transport.close

Basic Server Usage

$:.push File.expand_path('gen-rb', __dir__)
require 'thrift'
require 'calculator'

class CalculatorHandler
  def add(a, b)
    a + b
  end
end

handler            = CalculatorHandler.new
processor          = Calculator::Processor.new(handler)
server_transport   = Thrift::ServerSocket.new(9090)
transport_factory  = Thrift::BufferedTransportFactory.new
protocol_factory   = Thrift::BinaryProtocolFactory.new

server = Thrift::ThreadedServer.new(processor, server_transport,
                                    transport_factory, protocol_factory)
server.serve

Development and Tests

More Ruby Code

Breaking Changes

0.24.0

Connect timeout handling changed for both Thrift::Socket and Thrift::SSLSocket.

If your application matched NOT_OPEN for connect timeout handling, update it to handle TIMED_OUT. If you relied on timeout = 0 meaning immediate failure or on repeated retries extending the effective timeout during TCP fallback or TLS handshake, update those call paths before upgrading.

Ruby server socket transports now apply a 5-second timeout to accepted client sockets by default. This prevents stalled clients from blocking server threads indefinitely during response writes. Applications that intentionally require blocking accepted sockets can pass client_timeout: nil or client_timeout: 0 when constructing Thrift::ServerSocket, Thrift::SSLServerSocket, or Thrift::UNIXServerSocket.

Generated Ruby structs and unions now suffix field ID constants as *_FIELD_ID instead of exposing bare uppercased field names. For example, MyStruct::FOO becomes MyStruct::FOO_FIELD_ID. This avoids collisions with the generated FIELDS metadata hash for field names such as fields, but it is a source-compatible break if your application referenced the old constants directly. Regenerate Ruby code and update those constant references atomically.

Ruby binary protocol writers now enforce signed Thrift integer ranges before serializing values. byte, i16, i32, and i64 writes reject values outside their declared signed ranges, and binary/string/container sizes must fit in a non-negative signed i32 length. Older releases could silently wrap or clip some out-of-range values, such as writing 255 as a byte that read back as -1. This applies to both Thrift::BinaryProtocol and Thrift::BinaryProtocolAccelerated.

0.23.0

The documented source-build flow now effectively requires Ruby 2.7+. The committed development bundle no longer resolves on Ruby 2.6 (json-2.18.1 requires ruby version >= 2.7), so building and testing this library from source should be treated as 2.7+.

Generated structs and unions now consistently raise Thrift::ProtocolException::INVALID_DATA for invalid payloads such as unset required fields, invalid enum values, or invalid union state. If your application or tests matched older exception types or messages, update them.

Regenerated Ruby clients now validate replies more strictly. Mismatched reply message types, method names, or sequence IDs raise Thrift::ApplicationException::INVALID_MESSAGE_TYPE, Thrift::ApplicationException::WRONG_METHOD_NAME, or Thrift::ApplicationException::BAD_SEQUENCE_ID. If you relied on older, looser reply handling in servers, proxies, or tests, regenerate and update those call paths together.

Generated Ruby clients have never been safe to share across concurrent threads. A client tracks pending sequence IDs on a single reply stream, so use one client/transport pair per thread or serialize access yourself.

Treat Thrift::ApplicationException::BAD_SEQUENCE_ID as a correctness bug that needs immediate attention. It means the client read a reply whose sequence ID did not match the next pending request, so the connection may already be out of sync and you may be reading a reply intended for a different call. The most common cause is sharing one client across threads, but a buggy proxy or server can also cause it.

0.13.0

Ruby development and CI moved to Ruby 2.4+, but the runtime still claimed support for older interpreters. Treat Ruby < 2.4 on the 0.13.x line as best-effort, not guaranteed.

Migration Notes

Runtime Notes