bones-rpc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +8 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +29 -0
  8. data/Rakefile +1 -0
  9. data/bones-rpc.gemspec +29 -0
  10. data/lib/bones-rpc.rb +2 -0
  11. data/lib/bones/rpc.rb +23 -0
  12. data/lib/bones/rpc/adapter.rb +49 -0
  13. data/lib/bones/rpc/adapter/base.rb +41 -0
  14. data/lib/bones/rpc/adapter/erlang.rb +28 -0
  15. data/lib/bones/rpc/adapter/json.rb +23 -0
  16. data/lib/bones/rpc/adapter/msgpack.rb +52 -0
  17. data/lib/bones/rpc/adapter/parser.rb +37 -0
  18. data/lib/bones/rpc/address.rb +167 -0
  19. data/lib/bones/rpc/cluster.rb +266 -0
  20. data/lib/bones/rpc/connection.rb +146 -0
  21. data/lib/bones/rpc/connection/reader.rb +49 -0
  22. data/lib/bones/rpc/connection/socket.rb +4 -0
  23. data/lib/bones/rpc/connection/socket/connectable.rb +196 -0
  24. data/lib/bones/rpc/connection/socket/ssl.rb +35 -0
  25. data/lib/bones/rpc/connection/socket/tcp.rb +28 -0
  26. data/lib/bones/rpc/connection/writer.rb +51 -0
  27. data/lib/bones/rpc/context.rb +48 -0
  28. data/lib/bones/rpc/errors.rb +33 -0
  29. data/lib/bones/rpc/failover.rb +38 -0
  30. data/lib/bones/rpc/failover/disconnect.rb +33 -0
  31. data/lib/bones/rpc/failover/ignore.rb +31 -0
  32. data/lib/bones/rpc/failover/retry.rb +39 -0
  33. data/lib/bones/rpc/future.rb +26 -0
  34. data/lib/bones/rpc/instrumentable.rb +41 -0
  35. data/lib/bones/rpc/instrumentable/log.rb +45 -0
  36. data/lib/bones/rpc/instrumentable/noop.rb +33 -0
  37. data/lib/bones/rpc/loggable.rb +112 -0
  38. data/lib/bones/rpc/node.rb +317 -0
  39. data/lib/bones/rpc/node/registry.rb +32 -0
  40. data/lib/bones/rpc/parser.rb +114 -0
  41. data/lib/bones/rpc/parser/buffer.rb +80 -0
  42. data/lib/bones/rpc/protocol.rb +106 -0
  43. data/lib/bones/rpc/protocol/acknowledge.rb +82 -0
  44. data/lib/bones/rpc/protocol/adapter_helper.rb +164 -0
  45. data/lib/bones/rpc/protocol/binary_helper.rb +431 -0
  46. data/lib/bones/rpc/protocol/ext_message.rb +86 -0
  47. data/lib/bones/rpc/protocol/notify.rb +38 -0
  48. data/lib/bones/rpc/protocol/request.rb +45 -0
  49. data/lib/bones/rpc/protocol/response.rb +58 -0
  50. data/lib/bones/rpc/protocol/synchronize.rb +70 -0
  51. data/lib/bones/rpc/read_preference.rb +43 -0
  52. data/lib/bones/rpc/read_preference/nearest.rb +57 -0
  53. data/lib/bones/rpc/read_preference/selectable.rb +81 -0
  54. data/lib/bones/rpc/readable.rb +57 -0
  55. data/lib/bones/rpc/session.rb +195 -0
  56. data/lib/bones/rpc/uri.rb +222 -0
  57. data/lib/bones/rpc/version.rb +6 -0
  58. metadata +198 -0
@@ -0,0 +1,195 @@
1
+ # encoding: utf-8
2
+ require 'bones/rpc/read_preference'
3
+ require 'bones/rpc/readable'
4
+ require 'bones/rpc/cluster'
5
+ require 'bones/rpc/context'
6
+
7
+ module Bones
8
+ module RPC
9
+
10
+ # A session in bones_rpc is root for all interactions with a Bones::RPC server or
11
+ # replica set.
12
+ #
13
+ # It can talk to a single default database, or dynamically speak to multiple
14
+ # databases.
15
+ #
16
+ # @example Single database (console-style)
17
+ # session = Bones::RPC::Session.new(["127.0.0.1:27017"])
18
+ # session.use(:bones_rpc)
19
+ # session[:users].find.one
20
+ #
21
+ # @example Multiple databases
22
+ # session = Bones::RPC::Session.new(["127.0.0.1:27017"])
23
+ # session.with(database: :admin) do |admin|
24
+ # admin.command(ismaster: 1)
25
+ # end
26
+ #
27
+ # @example Authentication
28
+ # session = Bones::RPC::Session.new %w[127.0.0.1:27017],
29
+ # session.with(database: "admin").login("admin", "s3cr3t")
30
+ #
31
+ # @since 1.0.0
32
+ class Session
33
+ include Optionable
34
+
35
+ # @!attribute cluster
36
+ # @return [ Cluster ] The cluster of nodes.
37
+ # @!attribute options
38
+ # @return [ Hash ] The configuration options.
39
+ attr_reader :cluster, :options
40
+
41
+ # Run +command+ on the current database.
42
+ #
43
+ # @param (see Bones::RPC::Database#command)
44
+ #
45
+ # @return (see Bones::RPC::Database#command)
46
+ #
47
+ # @since 1.0.0
48
+ def command(op)
49
+ current_database.command(op)
50
+ end
51
+
52
+ def context
53
+ @context ||= Context.new(self)
54
+ end
55
+
56
+ # Disconnects all nodes in the session's cluster. This should only be used
57
+ # in cases # where you know you're not going to use the cluster on the
58
+ # thread anymore and need to force the connections to close.
59
+ #
60
+ # @return [ true ] True if the disconnect succeeded.
61
+ #
62
+ # @since 1.2.0
63
+ def disconnect
64
+ cluster.disconnect
65
+ end
66
+
67
+ def handle_refresh(node)
68
+ @callback.call(node) if @callback
69
+ end
70
+
71
+ # Provide a string inspection for the session.
72
+ #
73
+ # @example Inspect the session.
74
+ # session.inspect
75
+ #
76
+ # @return [ String ] The string inspection.
77
+ #
78
+ # @since 1.4.0
79
+ def inspect
80
+ "<#{self.class.name} seeds=#{cluster.seeds}>"
81
+ end
82
+
83
+ # Setup validation of allowed read preference options.
84
+ #
85
+ # @since 2.0.0
86
+ option(:read).allow(
87
+ :nearest
88
+ )
89
+
90
+ # Setup validation of allowed database options. (Any string or symbol)
91
+ #
92
+ # @since 2.0.0
93
+ option(:adapter).allow(Optionable.any(String), Optionable.any(Symbol), Optionable.any(Module))
94
+
95
+ # Setup validation of allowed max retry options. (Any integer)
96
+ #
97
+ # @since 2.0.0
98
+ option(:max_retries).allow(Optionable.any(Integer))
99
+
100
+ # Setup validation of allowed pool size options. (Any integer)
101
+ #
102
+ # @since 2.0.0
103
+ option(:pool_size).allow(Optionable.any(Integer))
104
+
105
+ # Setup validation of allowed retry interval options. (Any numeric)
106
+ #
107
+ # @since 2.0.0
108
+ option(:retry_interval).allow(Optionable.any(Numeric))
109
+
110
+ # Setup validation of allowed reap interval options. (Any numeric)
111
+ #
112
+ # @since 2.0.0
113
+ option(:reap_interval).allow(Optionable.any(Numeric))
114
+
115
+ # Setup validation of allowed ssl options. (Any boolean)
116
+ #
117
+ # @since 2.0.0
118
+ option(:ssl).allow(true, false)
119
+
120
+ # Setup validation of allowed timeout options. (Any numeric)
121
+ #
122
+ # @since 2.0.0
123
+ option(:timeout).allow(Optionable.any(Numeric))
124
+
125
+ # Initialize a new database session.
126
+ #
127
+ # @example Initialize a new session.
128
+ # Session.new([ "localhost:27017" ])
129
+ #
130
+ # @param [ Array ] seeds An array of host:port pairs.
131
+ # @param [ Hash ] options The options for the session.
132
+ #
133
+ # @see Above options validations for allowed values in the options hash.
134
+ #
135
+ # @since 1.0.0
136
+ def initialize(seeds, options = {}, &callback)
137
+ validate_strict(options)
138
+ @options = options
139
+ @callback = callback
140
+ @cluster = Cluster.new(self, seeds)
141
+ end
142
+
143
+ def notify(method, *params)
144
+ context.notify(method, params)
145
+ end
146
+
147
+ # Get the read preference for the session. Will default to primary if none
148
+ # was provided.
149
+ #
150
+ # @example Get the session's read preference.
151
+ # session.read_preference
152
+ #
153
+ # @return [ Object ] The read preference.
154
+ #
155
+ # @since 2.0.0
156
+ def read_preference
157
+ @read_preference ||= ReadPreference.get(options[:read] || :nearest)
158
+ end
159
+
160
+ def request(method, *params)
161
+ context.request(method, params)
162
+ end
163
+
164
+ def synchronize
165
+ context.synchronize
166
+ end
167
+
168
+ class << self
169
+
170
+ # Create a new session from a URI.
171
+ #
172
+ # @example Initialize a new session.
173
+ # Session.connect("bones-rpc://localhost:27017/my_db")
174
+ #
175
+ # @param [ String ] Bones::RPC URI formatted string.
176
+ #
177
+ # @return [ Session ] The new session.
178
+ #
179
+ # @since 3.0.0
180
+ def connect(uri, &block)
181
+ uri = Uri.new(uri)
182
+ session = new(*uri.bones_rpc_arguments, &block)
183
+ session
184
+ end
185
+ end
186
+
187
+ private
188
+
189
+ def initialize_copy(_)
190
+ @options = @options.dup
191
+ @read_preference = nil
192
+ end
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,222 @@
1
+ # encoding: utf-8
2
+ module Bones
3
+ module RPC
4
+
5
+ # Parses Bones::RPC uri
6
+ #
7
+ # @since 1.3.0
8
+ class Uri
9
+
10
+ # Get the scheme pattern.
11
+ #
12
+ # @since 1.3.0
13
+ SCHEME = /(bones-rpc:\/\/)/
14
+
15
+ # The user name pattern.
16
+ #
17
+ # @since 1.3.0
18
+ USER = /([-.\w:]+)/
19
+
20
+ # The password pattern.
21
+ #
22
+ # @since 1.3.0
23
+ PASS = /([^@,]+)/
24
+
25
+ # The nodes pattern.
26
+ #
27
+ # @since 1.3.0
28
+ NODES = /((([-.\w]+)(?::(\w+))?,?)+)/
29
+
30
+ # The database pattern.
31
+ #
32
+ # @since 1.3.0
33
+ DATABASE = /(?:\/([-\w]+))?/
34
+
35
+ # The options pattern.
36
+ #
37
+ # @since 1.3.0
38
+ OPTIONS = /(?:\?(.+))/
39
+
40
+ # The full URI pattern.
41
+ #
42
+ # @since 1.3.0
43
+ URI = /#{SCHEME}(#{USER}:#{PASS}@)?#{NODES}#{DATABASE}#{OPTIONS}?/
44
+
45
+ # The options that have to do with write concerns.
46
+ #
47
+ # @since 2.0.0
48
+ WRITE_OPTIONS = [ "w", "j", "fsync", "wtimeout" ].freeze
49
+
50
+ # The mappings from read preferences in the URI to Bones::RPC's.
51
+ #
52
+ # @since 2.0.0
53
+ READ_MAPPINGS = {
54
+ "nearest" => :nearest,
55
+ "primary" => :primary,
56
+ "primarypreferred" => :primary_preferred,
57
+ "secondary" => :secondary,
58
+ "secondarypreferred" => :secondary_preferred
59
+ }.freeze
60
+
61
+ # @!attribute match
62
+ # @return [ Array ] The uri match.
63
+ attr_reader :match
64
+
65
+ # Helper to determine if authentication is provided
66
+ #
67
+ # @example Boolean response if username/password given
68
+ # uri.auth_provided?
69
+ #
70
+ # @return [ true, false ] If authorization is provided.
71
+ #
72
+ # @since 1.3.0
73
+ def auth_provided?
74
+ !username.nil? && !password.nil?
75
+ end
76
+
77
+ # Get the database provided in the URI.
78
+ #
79
+ # @example Get the database.
80
+ # uri.database
81
+ #
82
+ # @return [ String ] The database.
83
+ #
84
+ # @since 1.3.0
85
+ def database
86
+ @database ||= match[9]
87
+ end
88
+
89
+ # Get the hosts provided in the URI.
90
+ #
91
+ # @example Get the hosts.
92
+ # uri.hosts
93
+ #
94
+ # @return [ Array<String> ] The hosts.
95
+ #
96
+ # @since 1.3.0
97
+ def hosts
98
+ @hosts ||= match[5].split(",")
99
+ end
100
+
101
+ # Create the new uri from the provided string.
102
+ #
103
+ # @example Create the new uri.
104
+ # Bones::RPC::Uri.new(uri)
105
+ #
106
+ # @param [ String ] string The uri string.
107
+ #
108
+ # @since 1.3.0
109
+ def initialize(string)
110
+ @match = string.match(URI)
111
+ invalid_uri!(string) unless @match
112
+ end
113
+
114
+ # Raise a human readable error when improper URI provided
115
+ #
116
+ # @example Raise error and provide guidance on invalid URI
117
+ # Bones::RPC::Uri.invalid!(uri)
118
+ #
119
+ # @param [ String ] Invalid string
120
+ #
121
+ # @since 1.3.1
122
+ def invalid_uri!(string)
123
+ scrubbed = string.gsub(/[^:]+@/, '<password>@')
124
+ raise Errors::InvalidBonesRPCURI, "The provided connection string is not a value URI: #{scrubbed}"
125
+ end
126
+
127
+ # Get the options provided in the URI.
128
+ #
129
+ # @example Get the options
130
+ # uri.options
131
+ #
132
+ # @note The options provided in the URI string must match the Bones::RPC
133
+ # specification.
134
+ #
135
+ # @return [ Hash ] Options hash usable by Moped
136
+ #
137
+ # @since 1.3.0
138
+ def options
139
+ options_string, options = match[10], {}
140
+ unless options_string.nil?
141
+ options_string.split(/\&/).each do |option_string|
142
+ key, value = option_string.split(Regexp.new('='))
143
+ if WRITE_OPTIONS.include?(key)
144
+ options[:write] = { key.to_sym => cast(value) }
145
+ elsif read = READ_MAPPINGS[value.downcase]
146
+ options[:read] = read
147
+ else
148
+ options[key.to_sym] = cast(value)
149
+ end
150
+ end
151
+ end
152
+ options
153
+ end
154
+
155
+ # Get the password provided in the URI.
156
+ #
157
+ # @example Get the password.
158
+ # uri.password
159
+ #
160
+ # @return [ String ] The password.
161
+ #
162
+ # @since 1.3.0
163
+ def password
164
+ @password ||= match[4]
165
+ end
166
+
167
+ # Get the uri as a Bones::RPC friendly configuration hash.
168
+ #
169
+ # @example Get the uri as a hash.
170
+ # uri.to_hash
171
+ #
172
+ # @return [ Hash ] The uri as options.
173
+ #
174
+ # @since 1.3.0
175
+ def to_hash
176
+ config = { database: database, hosts: hosts }
177
+ if username && password
178
+ config.merge!(username: username, password: password)
179
+ end
180
+ config
181
+ end
182
+
183
+ # Create Bones::RPC usable arguments
184
+ #
185
+ # @example Get the bones_rpc args
186
+ # uri.bones_rpc_arguments
187
+ #
188
+ # @return [ Array ] Array of arguments usable by bones_rpc
189
+ #
190
+ # @since 1.3.0
191
+ def bones_rpc_arguments
192
+ [ hosts, options ]
193
+ end
194
+
195
+ # Get the username provided in the URI.
196
+ #
197
+ # @example Get the username.
198
+ # uri.username
199
+ #
200
+ # @return [ String ] The username.
201
+ #
202
+ # @since 1.3.0
203
+ def username
204
+ @username ||= match[3]
205
+ end
206
+
207
+ private
208
+
209
+ def cast(value)
210
+ if value == "true"
211
+ true
212
+ elsif value == "false"
213
+ false
214
+ elsif value =~ /[\d]/
215
+ value.to_i
216
+ else
217
+ value.to_sym
218
+ end
219
+ end
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+ module Bones
3
+ module RPC
4
+ VERSION = "0.0.1"
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,198 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bones-rpc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Bennett
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: celluloid
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: celluloid-io
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: erlang-etf
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: msgpack
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: optionable
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '1.3'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '1.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Bones::RPC client for ruby
112
+ email:
113
+ - andrew@delorum.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - .ruby-gemset
120
+ - .ruby-version
121
+ - Gemfile
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - bones-rpc.gemspec
126
+ - lib/bones-rpc.rb
127
+ - lib/bones/rpc.rb
128
+ - lib/bones/rpc/adapter.rb
129
+ - lib/bones/rpc/adapter/base.rb
130
+ - lib/bones/rpc/adapter/erlang.rb
131
+ - lib/bones/rpc/adapter/json.rb
132
+ - lib/bones/rpc/adapter/msgpack.rb
133
+ - lib/bones/rpc/adapter/parser.rb
134
+ - lib/bones/rpc/address.rb
135
+ - lib/bones/rpc/cluster.rb
136
+ - lib/bones/rpc/connection.rb
137
+ - lib/bones/rpc/connection/reader.rb
138
+ - lib/bones/rpc/connection/socket.rb
139
+ - lib/bones/rpc/connection/socket/connectable.rb
140
+ - lib/bones/rpc/connection/socket/ssl.rb
141
+ - lib/bones/rpc/connection/socket/tcp.rb
142
+ - lib/bones/rpc/connection/writer.rb
143
+ - lib/bones/rpc/context.rb
144
+ - lib/bones/rpc/errors.rb
145
+ - lib/bones/rpc/failover.rb
146
+ - lib/bones/rpc/failover/disconnect.rb
147
+ - lib/bones/rpc/failover/ignore.rb
148
+ - lib/bones/rpc/failover/retry.rb
149
+ - lib/bones/rpc/future.rb
150
+ - lib/bones/rpc/instrumentable.rb
151
+ - lib/bones/rpc/instrumentable/log.rb
152
+ - lib/bones/rpc/instrumentable/noop.rb
153
+ - lib/bones/rpc/loggable.rb
154
+ - lib/bones/rpc/node.rb
155
+ - lib/bones/rpc/node/registry.rb
156
+ - lib/bones/rpc/parser.rb
157
+ - lib/bones/rpc/parser/buffer.rb
158
+ - lib/bones/rpc/protocol.rb
159
+ - lib/bones/rpc/protocol/acknowledge.rb
160
+ - lib/bones/rpc/protocol/adapter_helper.rb
161
+ - lib/bones/rpc/protocol/binary_helper.rb
162
+ - lib/bones/rpc/protocol/ext_message.rb
163
+ - lib/bones/rpc/protocol/notify.rb
164
+ - lib/bones/rpc/protocol/request.rb
165
+ - lib/bones/rpc/protocol/response.rb
166
+ - lib/bones/rpc/protocol/synchronize.rb
167
+ - lib/bones/rpc/read_preference.rb
168
+ - lib/bones/rpc/read_preference/nearest.rb
169
+ - lib/bones/rpc/read_preference/selectable.rb
170
+ - lib/bones/rpc/readable.rb
171
+ - lib/bones/rpc/session.rb
172
+ - lib/bones/rpc/uri.rb
173
+ - lib/bones/rpc/version.rb
174
+ homepage: ''
175
+ licenses:
176
+ - MIT
177
+ metadata: {}
178
+ post_install_message:
179
+ rdoc_options: []
180
+ require_paths:
181
+ - lib
182
+ required_ruby_version: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - '>='
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ required_rubygems_version: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - '>='
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
192
+ requirements: []
193
+ rubyforge_project:
194
+ rubygems_version: 2.0.5
195
+ signing_key:
196
+ specification_version: 4
197
+ summary: Bones::RPC client for ruby
198
+ test_files: []