monga 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -35,9 +35,14 @@ module Monga::Clients
35
35
  # it will send foce_status! to all clients while timout happend
36
36
  # or while preferred status will be returned
37
37
  def force_status!
38
- conn = aquire_connection
39
- conn.is_master? do |status|
40
- @status = status
38
+ if connected?
39
+ conn = aquire_connection
40
+ conn.is_master? do |status|
41
+ @status = status
42
+ yield(@status) if block_given?
43
+ end
44
+ else
45
+ @status = nil
41
46
  yield(@status) if block_given?
42
47
  end
43
48
  end
@@ -2,7 +2,7 @@ module Monga
2
2
  class Connection
3
3
  extend Forwardable
4
4
 
5
- def_delegators :@connection, :connected?, :responses, :send_command, :is_master?, :port
5
+ def_delegators :@connection, :connected?, :responses, :send_command, :is_master?, :port, :primary?
6
6
 
7
7
  attr_reader :type
8
8
 
@@ -14,17 +14,17 @@ module Monga::Connections
14
14
  def append(data)
15
15
  @buffer << data
16
16
  @buffer_size = @buffer.bytesize
17
- job
17
+ parse
18
18
  @buffer
19
19
  end
20
20
 
21
- def job
22
- parse_meta if @position == 0
23
- parse_doc if @position > 0
21
+ def parse
22
+ parse_meta if @position == 0
23
+ parse_doc if @position > 0
24
24
  end
25
25
 
26
26
  def parse_meta
27
- return if @buffer_size < 36
27
+ return if @buffer_size < 36
28
28
  @response = []
29
29
  @response << ::BinUtils.get_int32_le(@buffer, @position)
30
30
  @response << ::BinUtils.get_int32_le(@buffer, @position += 4)
@@ -41,21 +41,15 @@ module Monga::Connections
41
41
 
42
42
  def parse_doc
43
43
  while true
44
- if @number_returned == 0
45
- done
46
- break
47
- end
48
- break if @buffer_size < @position + 4
44
+ break if done
45
+ break if @buffer_size < @position + 4
49
46
  doc_length = ::BinUtils.get_int32_le(@buffer, @position)
50
- break if @buffer_size < @position + doc_length
47
+ break if @buffer_size < @position + doc_length
48
+
51
49
  doc = @buffer[@position, doc_length]
52
50
  @response[-1] << CBson.deserialize(doc)
53
51
  @position += doc_length
54
52
  @number_returned -= 1
55
- if @number_returned == 0
56
- done
57
- break
58
- end
59
53
  end
60
54
  end
61
55
 
@@ -66,6 +60,7 @@ module Monga::Connections
66
60
  end
67
61
 
68
62
  def done
63
+ return false if @number_returned > 0
69
64
  @responses << @response
70
65
  @response = nil
71
66
  if @buffer_size == @position
@@ -105,7 +105,7 @@ module Monga::Connections
105
105
  req = Monga::Protocol::Query.new(self, "admin", "$cmd", query: {"isMaster" => 1}, limit: 1)
106
106
  command = req.command
107
107
  request_id = req.request_id
108
- @responses[request_id] = proc do |data|
108
+ blk = proc do |data|
109
109
  err, resp = req.parse_response(data)
110
110
  if Exception === err
111
111
  @primary = false
@@ -115,6 +115,7 @@ module Monga::Connections
115
115
  yield @primary ? :primary : :secondary
116
116
  end
117
117
  end
118
+ @responses[request_id] = blk
118
119
  send_data command
119
120
  end
120
121
  end
@@ -6,7 +6,7 @@ module Monga::Connections
6
6
  # Importaint to say, that requests will be stored in this object only for `timeout` period.
7
7
  class EMProxyConnection
8
8
  # Pause while searching server in seconds
9
- WAIT = 0.1
9
+ WAIT = 0.05
10
10
 
11
11
  def initialize(client)
12
12
  @client = client
@@ -14,13 +14,13 @@ module Monga::Connections
14
14
  @requests = {}
15
15
  end
16
16
 
17
- # If timeout is defined then collect request and start timout.
18
- # If timout is not defined or zero then return exception.
17
+ # If timeout is defined then collect request and start timeout.
18
+ # If timeout is not defined or zero then return exception.
19
19
  def send_command(msg, request_id = nil, &cb)
20
20
  if @timeout && @timeout > 0
21
21
  @requests[request_id] = [msg, cb] if cb
22
- set_timeout
23
- find_server!
22
+ set_timeout unless @pending_timeout
23
+ find_server! unless @pending_server
24
24
  else
25
25
  error = Monga::Exceptions::Disconnected.new "Can't find appropriate server (all disconnected)"
26
26
  cb.call(error) if cb
@@ -29,48 +29,50 @@ module Monga::Connections
29
29
 
30
30
  # If timeout happend send exception to all collected requests.
31
31
  def set_timeout
32
- unless @pending_timeout
33
- @pending_timeout = true
34
- EM.add_timer(@timeout) do
35
- @pending_timeout = false
36
- @requests.keys.each do |request_id|
37
- msg, cb = @requests.delete request_id
38
- error = Monga::Exceptions::Disconnected.new "Can't find appropriate server (all disconnected)"
39
- cb.call(error)
40
- end
41
- end
32
+ @pending_timeout = EM::Timer.new(@timeout) do
33
+ @timeout_happend = true
34
+ end
35
+ end
36
+
37
+ def timeout_happend
38
+ @timeout_happend = false
39
+ @pending_timeout = false
40
+ @pending_server = false
41
+ @requests.keys.each do |request_id|
42
+ msg, cb = @requests.delete request_id
43
+ error = Monga::Exceptions::Disconnected.new "Can't find appropriate server (all disconnected)"
44
+ cb.call(error) if cb
42
45
  end
43
46
  end
44
47
 
45
48
  # Find server unless server is found
46
- def find_server!
47
- if !@pending_server && @pending_timeout
48
- @pending_server = true
49
- _count = 0
50
- @client.clients.each do |client|
51
- client.force_status! do |status|
52
- if status == :primary && [:primary, :primary_preferred, :secondary_preferred].include?(@client.read_pref)
53
- @pending_server = false
54
- server_found!
55
- elsif status == :secondary && [:secondary, :primary_preferred, :secondary_preferred].include?(@client.read_pref)
56
- @pending_server = false
57
- server_found!
58
- else
59
- EM.add_timer(WAIT) do
60
- EM.next_tick do
61
- @pending_server = false if (_count +=1) == @client.clients.size
62
- find_server!
63
- end
64
- end
49
+ def find_server!(i = 0)
50
+ @pending_server = true
51
+ if @pending_timeout && !@timeout_happend
52
+ size = @client.clients.size
53
+ client = @client.clients[i%size]
54
+ client.force_status! do |status|
55
+ if status == :primary && [:primary, :primary_preferred, :secondary_preferred].include?(@client.read_pref)
56
+ server_found!
57
+ elsif status == :secondary && [:secondary, :primary_preferred, :secondary_preferred].include?(@client.read_pref)
58
+ server_found!
59
+ else
60
+ EM::Timer.new(WAIT) do
61
+ find_server!(i+1)
65
62
  end
66
63
  end
67
64
  end
65
+ else
66
+ timeout_happend
68
67
  end
69
68
  end
70
69
 
71
70
  # YEEEHA! Send all collected requests back to client
72
71
  def server_found!
73
- @pending_timeout = false
72
+ @pending_server = false
73
+ @pending_timeout.cancel if @pending_timeout
74
+ @pending_timeout = nil
75
+ @timeout_happend = false
74
76
  @requests.keys.each do |request_id|
75
77
  msg, blk = @requests.delete request_id
76
78
  @client.aquire_connection.send_command(msg, request_id, &blk)
@@ -2,14 +2,14 @@ module Monga::Connections
2
2
  class FiberedProxyConnection < EMProxyConnection
3
3
  def send_command(msg, request_id = nil, &cb)
4
4
  if @timeout && @timeout > 0
5
- @requests[request_id] = [msg, @fib]
6
5
  @fib = Fiber.current
6
+ @requests[request_id] = [msg, @fib]
7
7
  set_timeout
8
8
  find_server!
9
9
  res = Fiber.yield
10
- @requests.delete(request_id)
11
10
  raise res if Exception === res
12
- @client.aquire_connection.send_command(msg, request_id, &cb)
11
+ conn = @client.aquire_connection
12
+ conn.send_command(msg, request_id, &cb)
13
13
  else
14
14
  error = Monga::Exceptions::Disconnected.new "Can't find appropriate server (all disconnected)"
15
15
  cb.call(error) if cb
@@ -17,7 +17,13 @@ module Monga::Connections
17
17
  end
18
18
 
19
19
  def server_found!
20
- @fib.resume
20
+ @pending_server = false
21
+ @pending_timeout.cancel if @pending_timeout
22
+ @pending_timeout = nil
23
+ @requests.keys.each do |req_id|
24
+ msg, fib = @requests.delete req_id
25
+ fib.call
26
+ end
21
27
  end
22
28
  end
23
29
  end
@@ -1,5 +1,5 @@
1
1
  require 'kgio'
2
- require 'io/nonblock'
2
+ require 'io/nonblock' # ha?
3
3
  module Monga::Connections
4
4
  class KGIOConnection
5
5
  def self.connect(host, port, timeout)
@@ -13,16 +13,22 @@ module Monga::Connections
13
13
  end
14
14
 
15
15
  def connected?
16
+ socket unless @connected
16
17
  @connected
17
18
  end
18
19
 
19
20
  def socket
20
21
  @socket ||= begin
21
22
  sock = Kgio::TCPSocket.new(@host, @port)
22
- sock.kgio_autopush = true
23
+ sock.kgio_autopush = true unless RUBY_PLATFORM['darwin']
24
+ # check connection
25
+ sock.kgio_write ""
26
+ # Macos doesn't support autopush
23
27
  @connected = true
24
28
  sock
25
29
  end
30
+ rescue => e
31
+ nil
26
32
  end
27
33
 
28
34
  # Fake answer, as far as we are blocking
@@ -31,6 +37,7 @@ module Monga::Connections
31
37
  end
32
38
 
33
39
  def send_command(msg, request_id=nil, &cb)
40
+ raise Errno::ECONNREFUSED, "Connection Refused" unless socket
34
41
  socket.kgio_write msg.to_s
35
42
  if cb
36
43
  read_socket
@@ -3,7 +3,7 @@ require 'timeout'
3
3
  module Monga::Connections
4
4
  class ProxyConnection
5
5
  # Pause while searching server in seconds
6
- WAIT = 0.1
6
+ WAIT = 0.3
7
7
 
8
8
  def initialize(client)
9
9
  @client = client
@@ -32,6 +32,8 @@ module Monga::Connections
32
32
  sleep(WAIT)
33
33
  end
34
34
  end
35
+ rescue Timeout::Error => e
36
+ raise Monga::Exceptions::Disconnected.new "Can't find appropriate server (all disconnected)"
35
37
  end
36
38
 
37
39
  # Find server unless server is found
data/lib/monga/cursor.rb CHANGED
@@ -248,7 +248,7 @@ module Monga
248
248
  def each_batch
249
249
  begin
250
250
  batch, more = next_batch
251
- yield batch
251
+ yield batch if more || batch
252
252
  end while more
253
253
  end
254
254
 
@@ -268,7 +268,7 @@ module Monga
268
268
  def each_doc
269
269
  begin
270
270
  doc, more = next_doc
271
- yield doc
271
+ yield doc if more || doc
272
272
  end while more
273
273
  end
274
274
  alias :each_document :each_doc
data/monga.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "monga"
7
- spec.version = "0.0.4"
7
+ spec.version = "0.0.5"
8
8
  spec.authors = ["Petr Yanovich"]
9
9
  spec.email = ["fl00r@yandex.ru"]
10
10
  spec.description = %q{MongoDB Ruby Evented Driver on EventMachine}
@@ -61,7 +61,8 @@ module Fake
61
61
  end
62
62
 
63
63
  def primary
64
- @si.rs.primary == @si if @si.rs
64
+ pr = @si.rs.primary == @si if @si.rs
65
+ pr
65
66
  end
66
67
 
67
68
  def receive_data(data)
@@ -82,12 +83,13 @@ module Fake
82
83
  # Single instance binded on one port.
83
84
  # Could be stopped or started.
84
85
  class SingleInstance
85
- attr_reader :rs
86
+ attr_reader :rs, :port
86
87
  attr_accessor :server
87
88
 
88
89
  def initialize(port, rs=nil)
89
90
  @rs = rs
90
91
  @port = port
92
+ EM.add_shutdown_hook{ @connected = false }
91
93
  end
92
94
 
93
95
  def start
@@ -4,12 +4,12 @@ describe Monga::Clients::ReplicaSetClient do
4
4
  before do
5
5
  @thread = Thread.new do
6
6
  EM.run do
7
- @replset = Fake::ReplicaSet.new([29000, 29100, 29200])
7
+ @replset = Fake::ReplicaSet.new([39000, 39100, 39200])
8
8
  @replset.start_all
9
9
  end
10
10
  end
11
11
  sleep 0.1
12
- @client = Monga::Client.new servers: ['127.0.0.1:29000', '127.0.0.1:29100', '127.0.0.1:29200'], type: :block, timeout: 1
12
+ @client = Monga::Client.new servers: ['127.0.0.1:39000', '127.0.0.1:39100', '127.0.0.1:39200'], type: :block, timeout: 1
13
13
  @collection = @client["dbTest"]["myCollection"]
14
14
  end
15
15
 
@@ -25,8 +25,8 @@ describe Monga::Clients::ReplicaSetClient do
25
25
  @collection.safe_insert(name: "Peter")
26
26
  @replset.primary.stop
27
27
  proc{ @collection.safe_insert(name: "Peter") }.must_raise Monga::Exceptions::Disconnected
28
- proc{ @collection.safe_insert(name: "Peter") }.must_raise Timeout::Error
29
- proc{ @collection.safe_insert(name: "Peter") }.must_raise Timeout::Error
28
+ proc{ @collection.safe_insert(name: "Peter") }.must_raise Monga::Exceptions::Disconnected
29
+ proc{ @collection.safe_insert(name: "Peter") }.must_raise Monga::Exceptions::Disconnected
30
30
  @replset.primary.start
31
31
  sleep(0.1)
32
32
  @collection.safe_insert(name: "Madonna")
@@ -50,9 +50,10 @@ describe Monga::Clients::ReplicaSetClient do
50
50
  @collection.safe_insert(name: "Peter")
51
51
  @replset.primary.stop
52
52
  proc{ @collection.safe_insert(name: "Peter") }.must_raise Monga::Exceptions::Disconnected
53
- proc{ @collection.safe_insert(name: "Peter") }.must_raise Timeout::Error
54
- proc{ @collection.safe_insert(name: "Peter") }.must_raise Timeout::Error
53
+ proc{ @collection.safe_insert(name: "Peter") }.must_raise Monga::Exceptions::Disconnected
54
+ proc{ @collection.safe_insert(name: "Peter") }.must_raise Monga::Exceptions::Disconnected
55
55
  @replset.vote
56
+ sleep 0.1
56
57
  @collection.safe_insert(name: "Madonna")
57
58
  end
58
59
  end
@@ -3,8 +3,9 @@ require 'spec_helper'
3
3
  describe Monga::Clients::ReplicaSetClient do
4
4
  before do
5
5
  EM.run do
6
- @replset = Fake::ReplicaSet.new([29000, 29100, 29200])
7
- @client = Monga::Client.new servers: ['127.0.0.1:29000', '127.0.0.1:29100', '127.0.0.1:29200'], type: :em, timeout: 1
6
+ @replset = Fake::ReplicaSet.new([39000, 39100, 39200])
7
+ @replset.start_all
8
+ @client = Monga::Client.new servers: ['127.0.0.1:39000', '127.0.0.1:39100', '127.0.0.1:39200'], type: :em, timeout: 1
8
9
  @collection = @client["dbTest"]["myCollection"]
9
10
  EM.stop
10
11
  end
@@ -3,9 +3,9 @@ require 'spec_helper'
3
3
  describe Monga::Clients::SingleInstanceClient do
4
4
  before do
5
5
  EM.synchrony do
6
- @client = Monga::Client.new port: 29000, type: :em
6
+ @client = Monga::Client.new port: 39000, type: :em
7
7
  @collection = @client["dbTest"]["myCollection"]
8
- @instance = Fake::SingleInstance.new(29000)
8
+ @instance = Fake::SingleInstance.new(39000)
9
9
  EM.stop
10
10
  end
11
11
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Monga::Database do
4
4
  before do
5
5
  EM.synchrony do
6
- @client = Monga::Client.new
6
+ @client = Monga::Client.new type: :sync
7
7
  @db = @client["dbTest"]
8
8
  @collection = @db["testCollection"]
9
9
  @collection.safe_remove
@@ -3,8 +3,9 @@ require 'spec_helper'
3
3
  describe Monga::Clients::ReplicaSetClient do
4
4
  before do
5
5
  EM.synchrony do
6
- @replset = Fake::ReplicaSet.new([29000, 29100, 29200])
7
- @client = Monga::Client.new servers: ['127.0.0.1:29000', '127.0.0.1:29100', '127.0.0.1:29200'], type: :sync, timeout: 1
6
+ @replset = Fake::ReplicaSet.new([19000, 19100, 19200])
7
+ @replset.start_all
8
+ @client = Monga::Client.new servers: ['127.0.0.1:19000', '127.0.0.1:19100', '127.0.0.1:19200'], type: :sync, timeout: 1
8
9
  @collection = @client["dbTest"]["myCollection"]
9
10
  EM.stop
10
11
  end
@@ -17,7 +18,7 @@ describe Monga::Clients::ReplicaSetClient do
17
18
  @replset.primary.stop
18
19
  proc{ @collection.safe_insert(name: "Peter") }.must_raise Monga::Exceptions::Disconnected
19
20
  proc{ @collection.safe_insert(name: "Peter") }.must_raise Monga::Exceptions::Disconnected
20
- EM.add_timer(0.5) do
21
+ EM.add_timer(0.1) do
21
22
  @replset.primary.start
22
23
  end
23
24
  @collection.safe_insert(name: "Peter")
@@ -3,8 +3,8 @@ require 'spec_helper'
3
3
  describe Monga::Clients::SingleInstanceClient do
4
4
  before do
5
5
  EM.synchrony do
6
- @instance = Fake::SingleInstance.new(29000)
7
- @client = Monga::Client.new port: 29000, type: :sync
6
+ @instance = Fake::SingleInstance.new(39000)
7
+ @client = Monga::Client.new port: 39000, type: :sync
8
8
  @collection = @client["dbTest"]["myCollection"]
9
9
  EM.stop
10
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monga
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-24 00:00:00.000000000 Z
12
+ date: 2013-04-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  requirement: !ruby/object:Gem::Requirement
@@ -194,7 +194,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
194
194
  requirements:
195
195
  - - ! '>='
196
196
  - !ruby/object:Gem::Version
197
- hash: 3881917270092852844
197
+ hash: 100645476183189099
198
198
  version: '0'
199
199
  segments:
200
200
  - 0
@@ -203,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
203
203
  requirements:
204
204
  - - ! '>='
205
205
  - !ruby/object:Gem::Version
206
- hash: 3881917270092852844
206
+ hash: 100645476183189099
207
207
  version: '0'
208
208
  segments:
209
209
  - 0