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.
- data/lib/monga/clients/single_instance_client.rb +8 -3
- data/lib/monga/connection.rb +1 -1
- data/lib/monga/connections/buffer.rb +10 -15
- data/lib/monga/connections/em_connection.rb +2 -1
- data/lib/monga/connections/em_proxy_connection.rb +37 -35
- data/lib/monga/connections/fibered_proxy_connection.rb +10 -4
- data/lib/monga/connections/kgio_connection.rb +9 -2
- data/lib/monga/connections/proxy_connection.rb +3 -1
- data/lib/monga/cursor.rb +2 -2
- data/monga.gemspec +1 -1
- data/spec/helpers/mongodb.rb +4 -2
- data/spec/monga/block/replica_set_client_spec.rb +7 -6
- data/spec/monga/em/replica_set_client_spec.rb +3 -2
- data/spec/monga/em/single_instance_client_spec.rb +2 -2
- data/spec/monga/sync/database_spec.rb +1 -1
- data/spec/monga/sync/replica_set_client_spec.rb +4 -3
- data/spec/monga/sync/single_instance_client_spec.rb +2 -2
- metadata +4 -4
@@ -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
|
-
|
39
|
-
|
40
|
-
|
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
|
data/lib/monga/connection.rb
CHANGED
@@ -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
|
-
|
17
|
+
parse
|
18
18
|
@buffer
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
22
|
-
parse_meta
|
23
|
-
parse_doc
|
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
|
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
|
45
|
-
|
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
|
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
|
-
|
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.
|
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
|
18
|
-
# If
|
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
|
-
|
33
|
-
@
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
@client.clients
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
-
@
|
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
|
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
|
-
@
|
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.
|
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.
|
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}
|
data/spec/helpers/mongodb.rb
CHANGED
@@ -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([
|
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:
|
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
|
29
|
-
proc{ @collection.safe_insert(name: "Peter") }.must_raise
|
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
|
54
|
-
proc{ @collection.safe_insert(name: "Peter") }.must_raise
|
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([
|
7
|
-
@
|
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:
|
6
|
+
@client = Monga::Client.new port: 39000, type: :em
|
7
7
|
@collection = @client["dbTest"]["myCollection"]
|
8
|
-
@instance = Fake::SingleInstance.new(
|
8
|
+
@instance = Fake::SingleInstance.new(39000)
|
9
9
|
EM.stop
|
10
10
|
end
|
11
11
|
end
|
@@ -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([
|
7
|
-
@
|
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.
|
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(
|
7
|
-
@client = Monga::Client.new port:
|
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
|
+
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-
|
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:
|
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:
|
206
|
+
hash: 100645476183189099
|
207
207
|
version: '0'
|
208
208
|
segments:
|
209
209
|
- 0
|