bones-rpc 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -6,7 +6,7 @@ module Bones
6
6
  # Provides the shared behaviour for read preferences that can filter by a
7
7
  # tag set or add query options.
8
8
  #
9
- # @since 2.0.0
9
+ # @since 0.0.1
10
10
  module Selectable
11
11
 
12
12
  # @!attribute tags
@@ -20,7 +20,7 @@ module Bones
20
20
  #
21
21
  # @param [ Array<Hash> ] tags The tag sets.
22
22
  #
23
- # @since 2.0.0
23
+ # @since 0.0.1
24
24
  def initialize(tags = nil)
25
25
  @tags = tags
26
26
  end
@@ -34,7 +34,7 @@ module Bones
34
34
  #
35
35
  # @return [ Hash ] The options plus additional query options.
36
36
  #
37
- # @since 2.0.0
37
+ # @since 0.0.1
38
38
  def query_options(options)
39
39
  options[:flags] ||= []
40
40
  options[:flags] |= [ :slave_ok ]
@@ -60,7 +60,7 @@ module Bones
60
60
  #
61
61
  # @return [ Object ] The result of the block.
62
62
  #
63
- # @since 2.0.0
63
+ # @since 0.0.1
64
64
  def with_retry(cluster, retries = cluster.max_retries, &block)
65
65
  begin
66
66
  block.call
@@ -4,7 +4,7 @@ module Bones
4
4
 
5
5
  # Provides behaviour around readable objects.
6
6
  #
7
- # @since 2.0.0
7
+ # @since 0.0.1
8
8
  module Readable
9
9
 
10
10
  private
@@ -18,7 +18,7 @@ module Bones
18
18
  #
19
19
  # @return [ Cluster ] The cluster.
20
20
  #
21
- # @since 2.0.0
21
+ # @since 0.0.1
22
22
  def cluster
23
23
  session.cluster
24
24
  end
@@ -32,7 +32,7 @@ module Bones
32
32
  #
33
33
  # @return [ Object ] The session's read preference.
34
34
  #
35
- # @since 2.0.0
35
+ # @since 0.0.1
36
36
  def read_preference
37
37
  session.read_preference
38
38
  end
@@ -48,7 +48,7 @@ module Bones
48
48
  #
49
49
  # @return [ Hash ] The new query options.
50
50
  #
51
- # @since 2.0.0
51
+ # @since 0.0.1
52
52
  def query_options(options = {})
53
53
  read_preference.query_options(options)
54
54
  end
@@ -28,7 +28,7 @@ module Bones
28
28
  # session = Bones::RPC::Session.new %w[127.0.0.1:27017],
29
29
  # session.with(database: "admin").login("admin", "s3cr3t")
30
30
  #
31
- # @since 1.0.0
31
+ # @since 0.0.1
32
32
  class Session
33
33
  include Optionable
34
34
 
@@ -38,13 +38,17 @@ module Bones
38
38
  # @return [ Hash ] The configuration options.
39
39
  attr_reader :cluster, :options
40
40
 
41
+ def backend
42
+ @backend ||= Backend.get(options[:backend] || :synchronous).tap(&:setup)
43
+ end
44
+
41
45
  # Run +command+ on the current database.
42
46
  #
43
47
  # @param (see Bones::RPC::Database#command)
44
48
  #
45
49
  # @return (see Bones::RPC::Database#command)
46
50
  #
47
- # @since 1.0.0
51
+ # @since 0.0.1
48
52
  def command(op)
49
53
  current_database.command(op)
50
54
  end
@@ -59,7 +63,7 @@ module Bones
59
63
  #
60
64
  # @return [ true ] True if the disconnect succeeded.
61
65
  #
62
- # @since 1.2.0
66
+ # @since 0.0.1
63
67
  def disconnect
64
68
  cluster.disconnect
65
69
  end
@@ -75,51 +79,56 @@ module Bones
75
79
  #
76
80
  # @return [ String ] The string inspection.
77
81
  #
78
- # @since 1.4.0
82
+ # @since 0.0.1
79
83
  def inspect
80
84
  "<#{self.class.name} seeds=#{cluster.seeds}>"
81
85
  end
82
86
 
83
87
  # Setup validation of allowed read preference options.
84
88
  #
85
- # @since 2.0.0
89
+ # @since 0.0.1
86
90
  option(:read).allow(
87
91
  :nearest
88
92
  )
89
93
 
90
- # Setup validation of allowed database options. (Any string or symbol)
94
+ # Setup validation of allowed adapter options. (Any string or symbol)
91
95
  #
92
- # @since 2.0.0
96
+ # @since 0.0.1
93
97
  option(:adapter).allow(Optionable.any(String), Optionable.any(Symbol), Optionable.any(Module))
94
98
 
99
+ # Setup validation of allowed backend options, (Any string or symbol)
100
+ #
101
+ # @since 0.0.1
102
+ option(:backend).allow(Optionable.any(String), Optionable.any(Symbol), Optionable.any(Module))
103
+
95
104
  # Setup validation of allowed max retry options. (Any integer)
96
105
  #
97
- # @since 2.0.0
106
+ # @since 0.0.1
98
107
  option(:max_retries).allow(Optionable.any(Integer))
99
108
 
100
109
  # Setup validation of allowed pool size options. (Any integer)
101
110
  #
102
- # @since 2.0.0
111
+ # @since 0.0.1
103
112
  option(:pool_size).allow(Optionable.any(Integer))
104
113
 
105
114
  # Setup validation of allowed retry interval options. (Any numeric)
106
115
  #
107
- # @since 2.0.0
116
+ # @since 0.0.1
108
117
  option(:retry_interval).allow(Optionable.any(Numeric))
109
118
 
110
119
  # Setup validation of allowed reap interval options. (Any numeric)
111
120
  #
112
- # @since 2.0.0
121
+ # @since 0.0.1
113
122
  option(:reap_interval).allow(Optionable.any(Numeric))
114
123
 
115
124
  # Setup validation of allowed ssl options. (Any boolean)
116
125
  #
117
- # @since 2.0.0
126
+ # @since 0.0.1
118
127
  option(:ssl).allow(true, false)
119
128
 
120
129
  # Setup validation of allowed timeout options. (Any numeric)
121
130
  #
122
- # @since 2.0.0
131
+ # @since 0.0.1
123
132
  option(:timeout).allow(Optionable.any(Numeric))
124
133
 
125
134
  # Initialize a new database session.
@@ -132,7 +141,7 @@ module Bones
132
141
  #
133
142
  # @see Above options validations for allowed values in the options hash.
134
143
  #
135
- # @since 1.0.0
144
+ # @since 0.0.1
136
145
  def initialize(seeds, options = {}, &callback)
137
146
  validate_strict(options)
138
147
  @options = options
@@ -152,7 +161,7 @@ module Bones
152
161
  #
153
162
  # @return [ Object ] The read preference.
154
163
  #
155
- # @since 2.0.0
164
+ # @since 0.0.1
156
165
  def read_preference
157
166
  @read_preference ||= ReadPreference.get(options[:read] || :nearest)
158
167
  end
@@ -176,7 +185,7 @@ module Bones
176
185
  #
177
186
  # @return [ Session ] The new session.
178
187
  #
179
- # @since 3.0.0
188
+ # @since 0.0.1
180
189
  def connect(uri, &block)
181
190
  uri = Uri.new(uri)
182
191
  session = new(*uri.bones_rpc_arguments, &block)
@@ -0,0 +1,2 @@
1
+ # encoding: utf-8
2
+ require 'bones/rpc/synchronous/node'
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+ require 'bones/rpc/connection'
3
+ require 'monitor'
4
+
5
+ module Bones
6
+ module RPC
7
+ module Synchronous
8
+
9
+ # This class contains behaviour of Bones::RPC socket connections.
10
+ #
11
+ # @since 0.0.1
12
+ class Connection < ::Bones::RPC::Connection
13
+
14
+ require 'bones/rpc/synchronous/connection/reader'
15
+ require 'bones/rpc/synchronous/connection/socket'
16
+ require 'bones/rpc/synchronous/connection/writer'
17
+
18
+ writer_class ::Bones::RPC::Synchronous::Connection::Writer
19
+
20
+ def write(operations)
21
+ with_connection do |socket|
22
+ proxy = writer.write(operations)
23
+ if proxy
24
+ Timeout::timeout(timeout) do
25
+ while not proxy.registry_empty?
26
+ writer.reader.read(proxy)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,59 @@
1
+ # encoding: utf-8
2
+ module Bones
3
+ module RPC
4
+ module Synchronous
5
+ class Connection
6
+ class Reader
7
+ def initialize(connection, socket, adapter, writer)
8
+ @connection = connection
9
+ @socket = socket
10
+ @adapter = adapter
11
+ @writer = writer
12
+ @alive = true
13
+ @buffer = ""
14
+ end
15
+
16
+ def alive?
17
+ !!@alive
18
+ end
19
+
20
+ def parse(data, proxy)
21
+ @buffer << data
22
+ if @buffer.empty?
23
+ read(proxy)
24
+ else
25
+ parser = Bones::RPC::Parser.new(@buffer, @adapter)
26
+ begin
27
+ loop { send parser.read, proxy }
28
+ rescue EOFError
29
+ @buffer.replace(parser.buffer.to_str)
30
+ end
31
+ return if @buffer.empty?
32
+ read(proxy)
33
+ end
34
+ end
35
+
36
+ def read(proxy)
37
+ parse @socket.readpartial(4096), proxy
38
+ rescue EOFError, Errors::ConnectionFailure => e
39
+ Loggable.warn(" BONES-RPC:", "#{@connection.node.address.resolved} Reader terminating: #{e.message}", "n/a")
40
+ terminate
41
+ raise e
42
+ end
43
+
44
+ def send(message, proxy)
45
+ proxy.handle_message(message)
46
+ end
47
+
48
+ def terminate
49
+ return if not alive?
50
+ @alive = false
51
+ @buffer.clear
52
+ @writer.terminate
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,4 @@
1
+ # encoding: utf-8
2
+ require 'bones/rpc/connection/socket'
3
+ require 'bones/rpc/synchronous/connection/socket/ssl'
4
+ require 'bones/rpc/synchronous/connection/socket/tcp'
@@ -0,0 +1,57 @@
1
+ # encoding: utf-8
2
+ require 'openssl'
3
+
4
+ module Bones
5
+ module RPC
6
+ module Synchronous
7
+ class Connection
8
+ module Socket
9
+
10
+ # This is a wrapper around a tcp socket.
11
+ class SSL < ::OpenSSL::SSL::SSLSocket
12
+ include ::Bones::RPC::Connection::Socket::Connectable
13
+
14
+ attr_reader :socket
15
+
16
+ # Initialize the new TCPSocket with SSL.
17
+ #
18
+ # @example Initialize the socket.
19
+ # SSL.new("127.0.0.1", 27017)
20
+ #
21
+ # @param [ String ] host The host.
22
+ # @param [ Integer ] port The port.
23
+ #
24
+ # @since 0.0.1
25
+ def initialize(remote_host, remote_port, local_host = nil, local_port = nil)
26
+ @host, @port = remote_host.to_s, remote_port
27
+ handle_socket_errors do
28
+ @socket = TCPSocket.new(@host, remote_port, local_host, local_port)
29
+ super(socket)
30
+ self.sync_close = true
31
+ connect
32
+ end
33
+ end
34
+
35
+ # Set the encoding of the underlying socket.
36
+ #
37
+ # @param [ String ] string The encoding.
38
+ #
39
+ # @since 0.0.1
40
+ def set_encoding(string)
41
+ socket.set_encoding(string)
42
+ end
43
+
44
+ # Set a socket option on the underlying socket.
45
+ #
46
+ # @param [ Array<Object> ] args The option arguments.
47
+ #
48
+ # @since 0.0.1
49
+ def setsockopt(*args)
50
+ socket.setsockopt(*args)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ module Bones
3
+ module RPC
4
+ module Synchronous
5
+ class Connection
6
+ module Socket
7
+
8
+ # This is a wrapper around a tcp socket.
9
+ class TCP < ::TCPSocket
10
+ include ::Bones::RPC::Connection::Socket::Connectable
11
+
12
+ # Initialize the new TCPSocket.
13
+ #
14
+ # @example Initialize the socket.
15
+ # TCP.new("127.0.0.1", 27017)
16
+ #
17
+ # @param [ String ] remote_host The host.
18
+ # @param [ Integer ] remote_port The port.
19
+ #
20
+ # @since 0.0.1
21
+ def initialize(remote_host, remote_port, local_host = nil, local_port = nil)
22
+ @host, @port = remote_host.to_s, remote_port
23
+ handle_socket_errors { super(@host, port, local_host, local_port) }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,86 @@
1
+ # encoding: utf-8
2
+ module Bones
3
+ module RPC
4
+ module Synchronous
5
+ class Connection
6
+ class Writer
7
+ attr_reader :reader
8
+
9
+ def initialize(connection, socket, adapter)
10
+ @connection = connection
11
+ @socket = socket
12
+ @adapter = adapter
13
+ @resolved = @connection.node.address.resolved
14
+ @alive = true
15
+ @buffer = ""
16
+ @reader = Reader.new(@connection, @socket, @adapter, self)
17
+ end
18
+
19
+ def alive?
20
+ !!@alive
21
+ end
22
+
23
+ def async
24
+ self
25
+ end
26
+
27
+ def write(operations)
28
+ proxy = NodeProxy.new(@connection.node)
29
+ operations.each do |message, future|
30
+ message.serialize(@buffer, @adapter)
31
+ message.attach(proxy, future) if future
32
+ end
33
+ @socket.write(@buffer)
34
+ @buffer = ""
35
+ return proxy
36
+ rescue EOFError, Errors::ConnectionFailure => e
37
+ Loggable.warn(" BONES-RPC:", "#{@resolved} Writer terminating: #{e.message}", "n/a")
38
+ terminate
39
+ raise e
40
+ end
41
+
42
+ def terminate
43
+ return if not alive?
44
+ @alive = false
45
+ @reader.terminate
46
+ @connection.cleanup_socket(@socket)
47
+ end
48
+
49
+ class NodeProxy < ::BasicObject
50
+ def attach(channel, id, future)
51
+ @registry.set(channel, id, future)
52
+ end
53
+
54
+ def detach(channel, id)
55
+ @registry.get(channel, id)
56
+ end
57
+
58
+ def handle_message(message)
59
+ logging(message) do
60
+ if future = message.get(self)
61
+ message.signal(future)
62
+ end
63
+ end
64
+ end
65
+
66
+ def initialize(node)
67
+ @node = node
68
+ @registry = Node::Registry.new
69
+ end
70
+
71
+ def registry_empty?
72
+ @registry.empty?
73
+ end
74
+
75
+ protected
76
+
77
+ def method_missing(name, *args, &block)
78
+ @node.__send__(name, *args, &block)
79
+ end
80
+ end
81
+
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end