From 502924d39fd4768641f378c635defe8de5f652af Mon Sep 17 00:00:00 2001 From: Dmytro Shteflyuk Date: Wed, 17 Dec 2025 10:17:37 -0500 Subject: [PATCH] Updated README.md for Ruby [skip ci] --- lib/rb/README.md | 192 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 175 insertions(+), 17 deletions(-) diff --git a/lib/rb/README.md b/lib/rb/README.md index b6e9a0792fc..b12bdcb10c9 100644 --- a/lib/rb/README.md +++ b/lib/rb/README.md @@ -1,7 +1,6 @@ -Thrift Ruby Software Library - http://thrift.apache.org +# Thrift Ruby Software Library -== LICENSE: +## License Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file @@ -20,24 +19,183 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -== DESCRIPTION: +# Using Thrift with Ruby -Thrift is a strongly-typed language-agnostic RPC system. -This library is the ruby implementation for both clients and servers. +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. -== INSTALL: +## Compatibility - $ gem install thrift +- Ruby MRI >= 2.7 (tested against current supported releases). +- JRuby works with the pure-Ruby implementation; the native extension is + skipped automatically. +- For the repo-wide transport, protocol, and server support matrix, see + [Language Feature Matrix](https://github.com/apache/thrift/blob/master/LANGUAGES.md). This README focuses on Ruby-specific + behavior and migration notes. -== CAVEATS: +## Installation -This library provides the client and server implementations of thrift. -It does not provide the compiler for the .thrift files. To compile -.thrift files into language-specific implementations, please download the full -thrift software package. +- Requirements: Ruby >= 2.7. +- From RubyGems: `gem install thrift` +- From source: `bundle install`, `gem build thrift.gemspec`, then install the + resulting `thrift-*.gem`. The native accelerator is built when the gem is + installed on supported runtimes. -== USAGE: +## Generating Ruby Code -This section should get written by someone with the time and inclination. -In the meantime, look at existing code, such as the benchmark or the tutorial -in the full thrift distribution. +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 + +- `bundle exec rake spec` runs the Ruby specs. It expects a built Thrift + compiler at `../../compiler/cpp/thrift`. +- `bundle exec rake test` runs the cross-language test suite; it must be + executed from a full Thrift checkout. +- `bundle exec rake build_ext` (implicit in the tasks above) compiles the + optional native extension that accelerates protocols and buffers. + +## More Ruby Code + +- Tutorial client and server: `tutorial/rb/RubyClient.rb` and `tutorial/rb/RubyServer.rb` +- Runtime benchmarks: `lib/rb/benchmark` +- Protocol benchmark: `test/rb/benchmarks/protocol_benchmark.rb` +- Library specs: `lib/rb/spec` +- Fuzzing harnesses and notes: `lib/rb/test/fuzz` +- Cross-language and integration tests: `test/rb` + +## Breaking Changes + +### 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. + +- Historical note for very old releases: the Ruby runtime was rearranged to use + more Ruby-like names, and generated files switched to underscored filenames. + If you are upgrading very old code, regenerate your Ruby bindings and update + any old `T*` constants or legacy require paths such as + `TBinaryProtocol` -> `Thrift::BinaryProtocol`. +- `rb:namespaced` changes the generated file layout. Flat output from + `thrift --gen rb` and namespaced output from `thrift --gen rb:namespaced` + use different require paths, so switch them atomically with regenerated code. + + # --gen rb + require 'calculator' + + # --gen rb:namespaced + require 'my_namespace/calculator' + +## Migration Notes + +- If you upgrade across the stricter reply-validation changes, regenerate all + Ruby stubs and deploy them with the matching Ruby runtime. Do not mix old + generated code, new generated code, and new runtime code on the same client + path without testing that combination. +- If you receive `Thrift::ApplicationException::BAD_SEQUENCE_ID`, treat the + connection as out of sync. Close it, create a new client/transport pair, and + investigate the root cause before retrying. +- Do not share one generated Ruby client across concurrent threads. Use one + client/transport pair per thread, or serialize access to a shared client. +- If you switch between `thrift --gen rb` and `thrift --gen rb:namespaced`, + regenerate all Ruby output and update `require` paths in the same change. + +## Runtime Notes + +- Loading the `thrift_native` extension changes which implementation you are + running. It replaces + `Thrift::Struct`, `Thrift::Union`, and `Thrift::CompactProtocol` methods + with C implementations in place. `Thrift::BinaryProtocol` remains available + in pure Ruby, and the C-backed binary protocol is opt-in through + `Thrift::BinaryProtocolAcceleratedFactory` or + `Thrift::BinaryProtocolAccelerated` when that class is available. +- The native extension is optional. If it cannot be built or loaded, Thrift + falls back to the pure-Ruby implementation. This mainly changes performance + and implementation details. +- JRuby skips the native extension automatically and uses the pure-Ruby path. +- Do not share one client instance across concurrent threads. A client tracks + request and reply state on a single transport stream. +- `Thrift::NonblockingServer` expects framed input. Use + `Thrift::FramedTransport` with it on the wire. +- Client and server must agree on transport and protocol choices. If you + switch to SSL, HTTP, header transport, compact protocol, or namespaced + generated code, update both ends together. +- HTTPS client transport verifies peers by default, and `Thrift::SSLSocket` + performs a hostname check against the host you pass in.