Rockin' Protobuf
in Ruby
BJ Neilsen
rand9.com
bj.neilsen@gmail.com
Definitions & Ideas
What is Protobuf?
Google's "lingua franca" for data
48,162 defined message types
12,183 .proto files
Fills ...
Structured Types
Messages, Enums, Services
Supported field types:
double, float, string, integer, boolean, bytes, composit...
Message
Struct-like data containers
Multiple fields, tagged numerically
Field tags shouldn't change once in use.*
mes...
Enum
Named, numeric "constants"
Useful for types and statuses
enum StatusType {
   PENDING = 0;
   ENABLED = 1;
...
Services
Group RPC endpoints (methods)
"Procedure" = name + request + response
Generated stubs, implementation s...
Compilation
$ gem install protobuffy
$ cd myapp
$ rprotoc proto/user.proto -o lib/
$ ls lib
user.pb.rb user_service.rb
Server
EventMachine backend
Can (should) run independent of your unciorn/thin processes
Register services by requiring the...
Service Implementations
Require and reopen stubbed class
RPC endpoints -> instance methods
Request/response as implicit...
Service Implementation (cont'd)
# file: app/services/user_service.rb
require 'lib/user_service'
class UserS...
Clients
EventMachine backend w/ async support
AJAX-style response callbacks
Pre/post serialization for free
request = User...
Examples
Upcoming SlideShare
Loading in …5
×

Rockin' Protobuf in Ruby

1,714 views

Published on

Published in: Technology
  • Be the first to comment

Rockin' Protobuf in Ruby

  1. 1. Rockin' Protobuf in Ruby BJ Neilsen rand9.com bj.neilsen@gmail.com
  2. 2. Definitions & Ideas
  3. 3. What is Protobuf? Google's "lingua franca" for data 48,162 defined message types 12,183 .proto files Fills three specific needs: Type Definition & Versioning Data Serialization Client/Server interchange (RPC)
  4. 4. Structured Types Messages, Enums, Services Supported field types: double, float, string, integer, boolean, bytes, composite (Message, Enum) Field requirements: required, optional, repeated (opt) Numeric field tags for serialized field position and versioning.
  5. 5. Message Struct-like data containers Multiple fields, tagged numerically Field tags shouldn't change once in use.* message User { required string guid = 1; optional string first_name = 2; optional string last_name = 3; repeated Friend friends = 4; optional int64 date_created = 5; optional bool is_active = 6 [default=false]; } * Unless you are brave
  6. 6. Enum Named, numeric "constants" Useful for types and statuses enum StatusType { PENDING = 0; ENABLED = 1; DISABLED = 2; DELETED = 3; } message User { # ... optional StatusType status = 7 [default=PENDING]; }
  7. 7. Services Group RPC endpoints (methods) "Procedure" = name + request + response Generated stubs, implementation still necessary. service UserService { rpc Find (UserFindRequest) returns (UserList); rpc Create (User) returns (User); rpc Update (User) returns (User); rpc Delete (User) returns (User); }
  8. 8. Compilation $ gem install protobuffy $ cd myapp $ rprotoc proto/user.proto -o lib/ $ ls lib user.pb.rb user_service.rb
  9. 9. Server EventMachine backend Can (should) run independent of your unciorn/thin processes Register services by requiring them (app/services/*.rb) # file: lib/pb_server.rb require 'protobuf/rpc/server' require 'app/services/user_service' include Protobuf EM::run { EM::start_server('localhost', 9933, Rpc::Server) }
  10. 10. Service Implementations Require and reopen stubbed class RPC endpoints -> instance methods Request/response as implicit objects Pre/post serialization for free Response helpers: rpc_failed(String or Exception) self.response=(Object) self.async_responder(boolean) send_response
  11. 11. Service Implementation (cont'd) # file: app/services/user_service.rb require 'lib/user_service' class UserService # Implicit request -> UserFindRequest # Implicit response -> UserList def find found = User.find_by_name(request.name) response.users << found end # ... other methods end
  12. 12. Clients EventMachine backend w/ async support AJAX-style response callbacks Pre/post serialization for free request = UserFindRequest.new request.name = 'jeff' UserService.client.find(request) do |c| c.on_failure do |e| logger.error('%s (%s)' % [e.message, e.code]) end c.on_success do |res| # res is a UserList object # handle successful response end end
  13. 13. Examples

×