monga 0.0.4 → 0.0.5

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.
@@ -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