bones-rpc 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-gemset +1 -1
  3. data/.ruby-version +1 -1
  4. data/bones-rpc.gemspec +1 -4
  5. data/lib/bones/rpc.rb +1 -1
  6. data/lib/bones/rpc/adapter.rb +44 -4
  7. data/lib/bones/rpc/adapter/json.rb +66 -0
  8. data/lib/bones/rpc/address.rb +6 -4
  9. data/lib/bones/rpc/backend.rb +31 -0
  10. data/lib/bones/rpc/backend/base.rb +30 -0
  11. data/lib/bones/rpc/backend/synchronous.rb +29 -0
  12. data/lib/bones/rpc/cluster.rb +18 -18
  13. data/lib/bones/rpc/connection.rb +19 -15
  14. data/lib/bones/rpc/connection/socket.rb +0 -2
  15. data/lib/bones/rpc/connection/socket/connectable.rb +15 -11
  16. data/lib/bones/rpc/context.rb +2 -2
  17. data/lib/bones/rpc/dns_resolver.rb +85 -0
  18. data/lib/bones/rpc/errors.rb +3 -0
  19. data/lib/bones/rpc/failover.rb +3 -3
  20. data/lib/bones/rpc/failover/disconnect.rb +2 -2
  21. data/lib/bones/rpc/failover/ignore.rb +2 -2
  22. data/lib/bones/rpc/failover/retry.rb +2 -2
  23. data/lib/bones/rpc/instrumentable.rb +3 -3
  24. data/lib/bones/rpc/instrumentable/log.rb +2 -2
  25. data/lib/bones/rpc/instrumentable/noop.rb +2 -2
  26. data/lib/bones/rpc/loggable.rb +8 -8
  27. data/lib/bones/rpc/node.rb +47 -37
  28. data/lib/bones/rpc/node/registry.rb +4 -0
  29. data/lib/bones/rpc/parser.rb +16 -5
  30. data/lib/bones/rpc/parser/buffer.rb +6 -2
  31. data/lib/bones/rpc/protocol/adapter_helper.rb +2 -2
  32. data/lib/bones/rpc/protocol/binary_helper.rb +2 -2
  33. data/lib/bones/rpc/read_preference.rb +3 -3
  34. data/lib/bones/rpc/read_preference/nearest.rb +3 -3
  35. data/lib/bones/rpc/read_preference/selectable.rb +4 -4
  36. data/lib/bones/rpc/readable.rb +4 -4
  37. data/lib/bones/rpc/session.rb +25 -16
  38. data/lib/bones/rpc/synchronous.rb +2 -0
  39. data/lib/bones/rpc/synchronous/connection.rb +36 -0
  40. data/lib/bones/rpc/synchronous/connection/reader.rb +59 -0
  41. data/lib/bones/rpc/synchronous/connection/socket.rb +4 -0
  42. data/lib/bones/rpc/synchronous/connection/socket/ssl.rb +57 -0
  43. data/lib/bones/rpc/synchronous/connection/socket/tcp.rb +30 -0
  44. data/lib/bones/rpc/synchronous/connection/writer.rb +86 -0
  45. data/lib/bones/rpc/synchronous/future.rb +91 -0
  46. data/lib/bones/rpc/synchronous/node.rb +45 -0
  47. data/lib/bones/rpc/uri.rb +20 -20
  48. data/lib/bones/rpc/version.rb +1 -1
  49. metadata +16 -52
  50. data/lib/bones/rpc/adapter/erlang.rb +0 -28
  51. data/lib/bones/rpc/adapter/msgpack.rb +0 -52
  52. data/lib/bones/rpc/connection/reader.rb +0 -49
  53. data/lib/bones/rpc/connection/socket/ssl.rb +0 -35
  54. data/lib/bones/rpc/connection/socket/tcp.rb +0 -28
  55. data/lib/bones/rpc/connection/writer.rb +0 -51
  56. data/lib/bones/rpc/future.rb +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cbf1eca258ffb6071f1299db7578fbcc9d98f121
4
- data.tar.gz: fe15de1e247f1ef12bdc24520a2b9cf520fadbb8
3
+ metadata.gz: 64b5fc8956bbbb066be3f8d398bc89cb2027f2be
4
+ data.tar.gz: 20261b3e59c98eb0693c7bc08f694c85af48f5c5
5
5
  SHA512:
6
- metadata.gz: 8e2ac1a8610ccfd42c5c9a257cc6cc21e0b2242b1e3582ee9ee0bbd3a73d2f902b29597c88676dc7767e51c2836ce20fd60cb5b1a70875f93dacbed56fe2ae67
7
- data.tar.gz: 6acdf3a32e6ab6a2df2a8643f3230e8bf0bd35255ffb7f1b8352fc0ca1a11be8b6d587740533f304587e69fc8c0d6f3917677c72111bc8a2c973ab1b744f6d91
6
+ metadata.gz: 84314e5a51a7723fd7455eeda8ced426375b5022b8ee2093ebdd50aecafc47345e3bea46d8b11f87c77f393d242e11942a249f0caac005a3112af7efa3fd3790
7
+ data.tar.gz: 32a75f9c693b9de01ffbb4f77d6ba25dcc799af9ded5f4686a5414c6b323c421813cf3597b3be7b27e4fc8ebe3d6bc9054f86c3057f35104b31c4648d4d720db
@@ -1 +1 @@
1
- bones
1
+ bones-rpc
@@ -1 +1 @@
1
- ruby-2.0.0
1
+ ruby-2.0.0
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.name = "bones-rpc"
8
8
  spec.version = Bones::RPC::VERSION
9
9
  spec.authors = ["Andrew Bennett"]
10
- spec.email = ["andrew@delorum.com"]
10
+ spec.email = ["andrew@pagodabox.com"]
11
11
  spec.description = %q{Bones::RPC client for ruby}
12
12
  spec.summary = %q{Bones::RPC client for ruby}
13
13
  spec.homepage = ""
@@ -18,9 +18,6 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "celluloid-io", ">= 0.14.0"
22
- spec.add_dependency "erlang-etf"
23
- spec.add_dependency "msgpack"
24
21
  spec.add_dependency "optionable"
25
22
 
26
23
  spec.add_development_dependency "bundler", "~> 1.3"
@@ -3,12 +3,12 @@ require 'logger'
3
3
  require 'stringio'
4
4
  require 'monitor'
5
5
  require 'timeout'
6
- require 'celluloid/io'
7
6
  require 'optionable'
8
7
  require 'bones/rpc/errors'
9
8
  require 'bones/rpc/loggable'
10
9
  require 'bones/rpc/uri'
11
10
  require 'bones/rpc/adapter'
11
+ require 'bones/rpc/backend'
12
12
  require 'bones/rpc/parser'
13
13
  require 'bones/rpc/protocol'
14
14
  require 'bones/rpc/session'
@@ -27,6 +27,50 @@ module Bones
27
27
  return adapter
28
28
  end
29
29
 
30
+ def read_ext(buffer)
31
+ ext_code, = buffer.read(1).unpack('C')
32
+ ext_length, = case ext_code
33
+ when 0xC7
34
+ buffer.read(1).unpack('C')
35
+ when 0xC8
36
+ buffer.read(2).unpack('n')
37
+ when 0xC9
38
+ buffer.read(4).unpack('N')
39
+ end
40
+ ext_type, = buffer.read(1).unpack('c')
41
+ ext_data = buffer.read(ext_length)
42
+ return ext_data
43
+ end
44
+
45
+ def write_ext(head, data, buffer = "")
46
+ ext_length = data.bytesize + 1
47
+ ext_code = if ext_length <= 0xFF
48
+ 0xC7
49
+ elsif ext_length <= 0xFFFF
50
+ 0xC8
51
+ elsif ext_length <= 0xFFFFFFFF
52
+ 0xC9
53
+ else
54
+ raise ArgumentError, "datasize too large: #{ext_length} (max #{0xFFFFFFFF} bytes)"
55
+ end
56
+ buffer << [ext_code].pack('C')
57
+ ext_length_packer = case ext_code
58
+ when 0xC7
59
+ 'C'
60
+ when 0xC8
61
+ 'n'
62
+ when 0xC9
63
+ 'N'
64
+ else
65
+ raise ArgumentError, "bad ext_code: #{ext_code} (should be one of #{0xC7}, #{0xC8}, #{0xC9})"
66
+ end
67
+ buffer << [ext_length].pack(ext_length_packer)
68
+ ext_type = 0x0D
69
+ buffer << [ext_type].pack('c')
70
+ buffer << [head].pack('C')
71
+ buffer << data.force_encoding('BINARY')
72
+ end
73
+
30
74
  private
31
75
 
32
76
  def adapters
@@ -41,9 +85,5 @@ module Bones
41
85
  end
42
86
 
43
87
  require 'bones/rpc/adapter/parser'
44
-
45
88
  require 'bones/rpc/adapter/base'
46
-
47
- require 'bones/rpc/adapter/erlang'
48
89
  require 'bones/rpc/adapter/json'
49
- require 'bones/rpc/adapter/msgpack'
@@ -16,6 +16,72 @@ module Bones
16
16
  ::JSON.load(buffer)
17
17
  end
18
18
 
19
+ def unpacker(data)
20
+ Unpacker.new(data)
21
+ end
22
+
23
+ def parser(data)
24
+ Adapter::Parser.new(self, data)
25
+ end
26
+
27
+ def unpacker_pos(parser)
28
+ parser.unpacker.buffer.pos
29
+ end
30
+
31
+ def unpacker_seek(parser, n)
32
+ parser.unpacker.buffer.seek(n)
33
+ return n
34
+ end
35
+
36
+ # I apologize for how nasty this unpacker is; Oj or Yajl would be better fits
37
+ class Unpacker
38
+ attr_reader :buffer
39
+
40
+ ARRAY_START = '['.freeze
41
+
42
+ def initialize(data)
43
+ @buffer = Bones::RPC::Parser::Buffer.new(data)
44
+ end
45
+
46
+ def read
47
+ if skip_to_array_start
48
+ unpack_stream("", buffer.pos)
49
+ else
50
+ nil
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def unpack_stream(temp, pos)
57
+ if char = buffer.getc
58
+ temp << char
59
+ term = begin
60
+ ::JSON.load(temp)
61
+ rescue ::JSON::ParserError
62
+ unpack_stream(temp, pos)
63
+ end
64
+ return term
65
+ else
66
+ buffer.seek(pos)
67
+ return nil
68
+ end
69
+ end
70
+
71
+ def skip_to_array_start
72
+ i = buffer.pos
73
+ case buffer.getc
74
+ when ARRAY_START
75
+ buffer.seek(i)
76
+ return true
77
+ when nil
78
+ return false
79
+ else
80
+ skip_to_array_start
81
+ end
82
+ end
83
+ end
84
+
19
85
  Adapter.register self
20
86
  end
21
87
  end
@@ -1,10 +1,12 @@
1
1
  # encoding: utf-8
2
+ require 'bones/rpc/dns_resolver'
3
+
2
4
  module Bones
3
5
  module RPC
4
6
 
5
7
  # Encapsulates behaviour around addresses and resolving dns.
6
8
  #
7
- # @since 2.0.0
9
+ # @since 0.0.1
8
10
  class Address
9
11
 
10
12
  # @!attribute host
@@ -26,7 +28,7 @@ module Bones
26
28
  #
27
29
  # @param [ String ] address The host:port pair as a string.
28
30
  #
29
- # @since 2.0.0
31
+ # @since 0.0.1
30
32
  def initialize(address, port = nil)
31
33
  if address.is_a?(Bones::RPC::Address)
32
34
  @host = address.host
@@ -97,7 +99,7 @@ module Bones
97
99
  #
98
100
  # @return [ String ] The resolved address.
99
101
  #
100
- # @since 2.0.0
102
+ # @since 0.0.1
101
103
  def resolve(node)
102
104
  begin
103
105
  resolve! unless valid?
@@ -151,7 +153,7 @@ module Bones
151
153
 
152
154
  # Guess it's not an IP address, so let's try DNS
153
155
  unless @ip
154
- addrs = Array(::Celluloid::IO::DNSResolver.new.resolve(@host))
156
+ addrs = Array(::Bones::RPC::DNSResolver.new.resolve(@host))
155
157
  raise Resolv::ResolvError, "DNS result has no information for #{@host}" if addrs.empty?
156
158
 
157
159
  # Pseudorandom round-robin DNS support :/
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+ module Bones
3
+ module RPC
4
+ module Backend
5
+ extend self
6
+
7
+ def get(backend_name)
8
+ backends[backend_name] || raise(Errors::InvalidBackend, "Unknown backend #{backend_name.inspect}")
9
+ end
10
+
11
+ def register(backend)
12
+ backend.send(:attr_reader, :backend_name)
13
+ backend.send(:include, Backend::Base)
14
+ backend.send(:extend, backend)
15
+ backends[backend] ||= backend
16
+ backends[backend.backend_name] ||= backend
17
+ backends[backend.backend_name.to_s] ||= backend
18
+ return backend
19
+ end
20
+
21
+ private
22
+
23
+ def backends
24
+ @backends ||= {}
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ require 'bones/rpc/backend/base'
31
+ require 'bones/rpc/backend/synchronous'
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ module Bones
3
+ module RPC
4
+ module Backend
5
+ module Base
6
+
7
+ def backend_name
8
+ raise NotImplementedError, "Backend #{self.name} does not implement #backend_name"
9
+ end
10
+
11
+ def setup
12
+ raise NotImplementedError, "Backend #{self.name} does not implement #setup"
13
+ end
14
+
15
+ def connection_class
16
+ raise NotImplementedError, "Backend #{self.name} does not implement #connection_class"
17
+ end
18
+
19
+ def future_class
20
+ raise NotImplementedError, "Backend #{self.name} does not implement #future_class"
21
+ end
22
+
23
+ def node_class
24
+ raise NotImplementedError, "Backend #{self.name} does not implement #node_class"
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+ module Bones
3
+ module RPC
4
+ module Backend
5
+ module Synchronous
6
+
7
+ @backend_name = :synchronous
8
+
9
+ def setup
10
+ require 'bones/rpc/synchronous'
11
+ end
12
+
13
+ def connection_class
14
+ ::Bones::RPC::Synchronous::Connection
15
+ end
16
+
17
+ def future_class
18
+ ::Bones::RPC::Synchronous::Future
19
+ end
20
+
21
+ def node_class
22
+ ::Bones::RPC::Synchronous::Node
23
+ end
24
+
25
+ Backend.register self
26
+ end
27
+ end
28
+ end
29
+ end
@@ -7,22 +7,22 @@ module Bones
7
7
  # The cluster represents a cluster of MongoDB server nodes, either a single
8
8
  # node, a replica set, or a mongos server.
9
9
  #
10
- # @since 1.0.0
10
+ # @since 0.0.1
11
11
  class Cluster
12
12
 
13
13
  # The default interval that a node would be flagged as "down".
14
14
  #
15
- # @since 2.0.0
15
+ # @since 0.0.1
16
16
  DOWN_INTERVAL = 30
17
17
 
18
18
  # The default interval that a node should be refreshed in.
19
19
  #
20
- # @since 2.0.0
20
+ # @since 0.0.1
21
21
  REFRESH_INTERVAL = 300
22
22
 
23
23
  # The default time to wait to retry an operation.
24
24
  #
25
- # @since 2.0.0
25
+ # @since 0.0.1
26
26
  RETRY_INTERVAL = 0.25
27
27
 
28
28
  # @!attribute options
@@ -39,7 +39,7 @@ module Bones
39
39
  #
40
40
  # @return [ true ] True if the disconnect succeeded.
41
41
  #
42
- # @since 1.2.0
42
+ # @since 0.0.1
43
43
  def disconnect
44
44
  nodes.each { |node| node.disconnect } and true
45
45
  end
@@ -52,7 +52,7 @@ module Bones
52
52
  #
53
53
  # @return [ Integer ] The down interval.
54
54
  #
55
- # @since 1.2.7
55
+ # @since 0.0.1
56
56
  def down_interval
57
57
  @down_interval ||= options[:down_interval] || DOWN_INTERVAL
58
58
  end
@@ -75,10 +75,10 @@ module Bones
75
75
  # @option options [ Integer ] :timeout The time in seconds to wait for an
76
76
  # operation to timeout. (5)
77
77
  #
78
- # @since 1.0.0
78
+ # @since 0.0.1
79
79
  def initialize(session, hosts)
80
80
  @session = session
81
- @seeds = hosts.map { |host| Node.new(self, Address.new(host)) }
81
+ @seeds = hosts.map { |host| session.backend.node_class.new(self, Address.new(host)) }
82
82
  @peers = []
83
83
  end
84
84
 
@@ -89,7 +89,7 @@ module Bones
89
89
  #
90
90
  # @return [ String ] A nicely formatted string.
91
91
  #
92
- # @since 1.0.0
92
+ # @since 0.0.1
93
93
  def inspect
94
94
  "#<#{self.class.name}:#{object_id} @seeds=#{seeds.inspect}>"
95
95
  end
@@ -102,7 +102,7 @@ module Bones
102
102
  #
103
103
  # @return [ Integer ] The max retries.
104
104
  #
105
- # @since 1.2.7
105
+ # @since 0.0.1
106
106
  def max_retries
107
107
  @max_retries ||= options[:max_retries] || seeds.size
108
108
  end
@@ -116,7 +116,7 @@ module Bones
116
116
  #
117
117
  # @return [ Array<Node> ] the list of available nodes.
118
118
  #
119
- # @since 1.0.0
119
+ # @since 0.0.1
120
120
  def nodes
121
121
  # Find the nodes that were down but are ready to be refreshed, or those
122
122
  # with stale connection information.
@@ -153,7 +153,7 @@ module Bones
153
153
  #
154
154
  # @return [ Array<Node> ] the available nodes
155
155
  #
156
- # @since 1.0.0
156
+ # @since 0.0.1
157
157
  def refresh(nodes_to_refresh = seeds)
158
158
  refreshed_nodes = []
159
159
  seen = {}
@@ -184,7 +184,7 @@ module Bones
184
184
  #
185
185
  # @return [ Integer ] The refresh interval.
186
186
  #
187
- # @since 1.2.7
187
+ # @since 0.0.1
188
188
  def refresh_interval
189
189
  @refresh_interval ||= options[:refresh_interval] || REFRESH_INTERVAL
190
190
  end
@@ -197,7 +197,7 @@ module Bones
197
197
  #
198
198
  # @return [ Integer ] The retry interval.
199
199
  #
200
- # @since 1.2.7
200
+ # @since 0.0.1
201
201
  def retry_interval
202
202
  @retry_interval ||= options[:retry_interval] || RETRY_INTERVAL
203
203
  end
@@ -213,7 +213,7 @@ module Bones
213
213
  #
214
214
  # @return [ Time ] The down boundary.
215
215
  #
216
- # @since 2.0.0
216
+ # @since 0.0.1
217
217
  def down_boundary
218
218
  Time.new - down_interval
219
219
  end
@@ -227,7 +227,7 @@ module Bones
227
227
  #
228
228
  # @return [ Time ] The refresh boundary.
229
229
  #
230
- # @since 2.0.0
230
+ # @since 0.0.1
231
231
  def refresh_boundary
232
232
  Time.new - refresh_interval
233
233
  end
@@ -243,7 +243,7 @@ module Bones
243
243
  #
244
244
  # @param [ Node ] node The Node to check.
245
245
  #
246
- # @since 2.0.0
246
+ # @since 0.0.1
247
247
  def refreshable?(node)
248
248
  node.down? ? node.down_at < down_boundary : node.needs_refresh?(refresh_boundary)
249
249
  end
@@ -257,7 +257,7 @@ module Bones
257
257
  #
258
258
  # @return [ Cluster ] The cloned cluster.
259
259
  #
260
- # @since 1.0.0
260
+ # @since 0.0.1
261
261
  def initialize_copy(_)
262
262
  @seeds = seeds.map(&:dup)
263
263
  end