blob: b12bdcb10c90cc32628314a22255ae139878b930 [file] [log] [blame] [view]
Dmytro Shteflyuk3f81e222025-12-17 10:17:37 -05001# Thrift Ruby Software Library
Mark Slee54b7ab92007-03-06 00:06:27 +00002
Dmytro Shteflyuk3f81e222025-12-17 10:17:37 -05003## License
Bryan Duxburydef30a62009-04-08 00:19:37 +00004
5Licensed to the Apache Software Foundation (ASF) under one
6or more contributor license agreements. See the NOTICE file
7distributed with this work for additional information
8regarding copyright ownership. The ASF licenses this file
9to you under the Apache License, Version 2.0 (the
10"License"); you may not use this file except in compliance
11with the License. You may obtain a copy of the License at
12
13 http://www.apache.org/licenses/LICENSE-2.0
14
15Unless required by applicable law or agreed to in writing,
16software distributed under the License is distributed on an
17"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18KIND, either express or implied. See the License for the
19specific language governing permissions and limitations
20under the License.
21
Dmytro Shteflyuk3f81e222025-12-17 10:17:37 -050022# Using Thrift with Ruby
Mark Slee54b7ab92007-03-06 00:06:27 +000023
Dmytro Shteflyuk3f81e222025-12-17 10:17:37 -050024Ruby bindings for the Apache Thrift RPC system. The gem contains the runtime
25types, transports, protocols, and servers used by generated Ruby code for both
26clients and services.
Kevin Clark1b8fec12008-06-24 01:06:08 +000027
Dmytro Shteflyuk3f81e222025-12-17 10:17:37 -050028## Compatibility
Kevin Clark1b8fec12008-06-24 01:06:08 +000029
Dmytro Shteflyuk3f81e222025-12-17 10:17:37 -050030- Ruby MRI >= 2.7 (tested against current supported releases).
31- JRuby works with the pure-Ruby implementation; the native extension is
32 skipped automatically.
33- For the repo-wide transport, protocol, and server support matrix, see
34 [Language Feature Matrix](https://github.com/apache/thrift/blob/master/LANGUAGES.md). This README focuses on Ruby-specific
35 behavior and migration notes.
Kevin Clark1b8fec12008-06-24 01:06:08 +000036
Dmytro Shteflyuk3f81e222025-12-17 10:17:37 -050037## Installation
Kevin Clark1b8fec12008-06-24 01:06:08 +000038
Dmytro Shteflyuk3f81e222025-12-17 10:17:37 -050039- Requirements: Ruby >= 2.7.
40- From RubyGems: `gem install thrift`
41- From source: `bundle install`, `gem build thrift.gemspec`, then install the
42 resulting `thrift-*.gem`. The native accelerator is built when the gem is
43 installed on supported runtimes.
Kevin Clark1b8fec12008-06-24 01:06:08 +000044
Dmytro Shteflyuk3f81e222025-12-17 10:17:37 -050045## Generating Ruby Code
Kevin Clark1b8fec12008-06-24 01:06:08 +000046
Dmytro Shteflyuk3f81e222025-12-17 10:17:37 -050047The Ruby library does not include the Thrift compiler. Use a compiler built
48from the root of this repository to generate Ruby bindings:
49
50 thrift --gen rb path/to/service.thrift
51 # with namespaced modules
52 thrift --gen rb:namespaced --recurse path/to/service.thrift
53
54Generated files are typically written to `gen-rb/` and can be required
55directly from your application.
56
57## Basic Client Usage
58
59 $:.push File.expand_path('gen-rb', __dir__)
60 require 'thrift'
61 require 'calculator'
62
63 socket = Thrift::Socket.new('localhost', 9090)
64 transport = Thrift::BufferedTransport.new(socket)
65 protocol = Thrift::BinaryProtocol.new(transport)
66 client = Calculator::Client.new(protocol)
67
68 transport.open
69 puts client.add(1, 1)
70 transport.close
71
72## Basic Server Usage
73
74 $:.push File.expand_path('gen-rb', __dir__)
75 require 'thrift'
76 require 'calculator'
77
78 class CalculatorHandler
79 def add(a, b)
80 a + b
81 end
82 end
83
84 handler = CalculatorHandler.new
85 processor = Calculator::Processor.new(handler)
86 server_transport = Thrift::ServerSocket.new(9090)
87 transport_factory = Thrift::BufferedTransportFactory.new
88 protocol_factory = Thrift::BinaryProtocolFactory.new
89
90 server = Thrift::ThreadedServer.new(processor, server_transport,
91 transport_factory, protocol_factory)
92 server.serve
93
94## Development and Tests
95
96- `bundle exec rake spec` runs the Ruby specs. It expects a built Thrift
97 compiler at `../../compiler/cpp/thrift`.
98- `bundle exec rake test` runs the cross-language test suite; it must be
99 executed from a full Thrift checkout.
100- `bundle exec rake build_ext` (implicit in the tasks above) compiles the
101 optional native extension that accelerates protocols and buffers.
102
103## More Ruby Code
104
105- Tutorial client and server: `tutorial/rb/RubyClient.rb` and `tutorial/rb/RubyServer.rb`
106- Runtime benchmarks: `lib/rb/benchmark`
107- Protocol benchmark: `test/rb/benchmarks/protocol_benchmark.rb`
108- Library specs: `lib/rb/spec`
109- Fuzzing harnesses and notes: `lib/rb/test/fuzz`
110- Cross-language and integration tests: `test/rb`
111
112## Breaking Changes
113
114### 0.23.0
115
116The documented source-build flow now effectively requires Ruby `2.7+`.
117The committed development bundle no longer resolves on Ruby `2.6`
118(`json-2.18.1 requires ruby version >= 2.7`), so building and testing this
119library from source should be treated as `2.7+`.
120
121Generated structs and unions now consistently raise
122`Thrift::ProtocolException::INVALID_DATA` for invalid payloads such as unset
123required fields, invalid enum values, or invalid union state. If your
124application or tests matched older exception types or messages, update them.
125
126Regenerated Ruby clients now validate replies more strictly. Mismatched reply
127message types, method names, or sequence IDs raise
128`Thrift::ApplicationException::INVALID_MESSAGE_TYPE`,
129`Thrift::ApplicationException::WRONG_METHOD_NAME`, or
130`Thrift::ApplicationException::BAD_SEQUENCE_ID`. If you relied on older,
131looser reply handling in servers, proxies, or tests, regenerate and update
132those call paths together.
133
134Generated Ruby clients have never been safe to share across concurrent
135threads. A client tracks pending sequence IDs on a single reply stream, so use
136one client/transport pair per thread or serialize access yourself.
137
138Treat `Thrift::ApplicationException::BAD_SEQUENCE_ID` as a correctness bug
139that needs immediate attention. It means the client read a reply whose
140sequence ID did not match the next pending request, so the connection may
141already be out of sync and you may be reading a reply intended for a
142different call. The most common cause is sharing one client across threads,
143but a buggy proxy or server can also cause it.
144
145### 0.13.0
146
147Ruby development and CI moved to Ruby `2.4+`, but the runtime still claimed
148support for older interpreters. Treat Ruby `< 2.4` on the `0.13.x` line as
149best-effort, not guaranteed.
150
151- Historical note for very old releases: the Ruby runtime was rearranged to use
152 more Ruby-like names, and generated files switched to underscored filenames.
153 If you are upgrading very old code, regenerate your Ruby bindings and update
154 any old `T*` constants or legacy require paths such as
155 `TBinaryProtocol` -> `Thrift::BinaryProtocol`.
156- `rb:namespaced` changes the generated file layout. Flat output from
157 `thrift --gen rb` and namespaced output from `thrift --gen rb:namespaced`
158 use different require paths, so switch them atomically with regenerated code.
159
160 # --gen rb
161 require 'calculator'
162
163 # --gen rb:namespaced
164 require 'my_namespace/calculator'
165
166## Migration Notes
167
168- If you upgrade across the stricter reply-validation changes, regenerate all
169 Ruby stubs and deploy them with the matching Ruby runtime. Do not mix old
170 generated code, new generated code, and new runtime code on the same client
171 path without testing that combination.
172- If you receive `Thrift::ApplicationException::BAD_SEQUENCE_ID`, treat the
173 connection as out of sync. Close it, create a new client/transport pair, and
174 investigate the root cause before retrying.
175- Do not share one generated Ruby client across concurrent threads. Use one
176 client/transport pair per thread, or serialize access to a shared client.
177- If you switch between `thrift --gen rb` and `thrift --gen rb:namespaced`,
178 regenerate all Ruby output and update `require` paths in the same change.
179
180## Runtime Notes
181
182- Loading the `thrift_native` extension changes which implementation you are
183 running. It replaces
184 `Thrift::Struct`, `Thrift::Union`, and `Thrift::CompactProtocol` methods
185 with C implementations in place. `Thrift::BinaryProtocol` remains available
186 in pure Ruby, and the C-backed binary protocol is opt-in through
187 `Thrift::BinaryProtocolAcceleratedFactory` or
188 `Thrift::BinaryProtocolAccelerated` when that class is available.
189- The native extension is optional. If it cannot be built or loaded, Thrift
190 falls back to the pure-Ruby implementation. This mainly changes performance
191 and implementation details.
192- JRuby skips the native extension automatically and uses the pure-Ruby path.
193- Do not share one client instance across concurrent threads. A client tracks
194 request and reply state on a single transport stream.
195- `Thrift::NonblockingServer` expects framed input. Use
196 `Thrift::FramedTransport` with it on the wire.
197- Client and server must agree on transport and protocol choices. If you
198 switch to SSL, HTTP, header transport, compact protocol, or namespaced
199 generated code, update both ends together.
200- HTTPS client transport verifies peers by default, and `Thrift::SSLSocket`
201 performs a hostname check against the host you pass in.