monga 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +9 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +110 -0
  5. data/Rakefile +13 -0
  6. data/lib/monga/client.rb +8 -0
  7. data/lib/monga/clients/client.rb +24 -0
  8. data/lib/monga/clients/master_slave_client.rb +5 -0
  9. data/lib/monga/clients/replica_set_client.rb +101 -0
  10. data/lib/monga/collection.rb +108 -0
  11. data/lib/monga/connection.rb +23 -0
  12. data/lib/monga/connection_pool.rb +38 -0
  13. data/lib/monga/connections/em_connection.rb +152 -0
  14. data/lib/monga/connections/primary.rb +46 -0
  15. data/lib/monga/connections/secondary.rb +13 -0
  16. data/lib/monga/cursor.rb +175 -0
  17. data/lib/monga/database.rb +97 -0
  18. data/lib/monga/exceptions.rb +9 -0
  19. data/lib/monga/miner.rb +72 -0
  20. data/lib/monga/request.rb +122 -0
  21. data/lib/monga/requests/delete.rb +23 -0
  22. data/lib/monga/requests/get_more.rb +19 -0
  23. data/lib/monga/requests/insert.rb +29 -0
  24. data/lib/monga/requests/kill_cursors.rb +25 -0
  25. data/lib/monga/requests/query.rb +49 -0
  26. data/lib/monga/requests/update.rb +25 -0
  27. data/lib/monga/response.rb +11 -0
  28. data/lib/monga.rb +30 -0
  29. data/monga.gemspec +26 -0
  30. data/spec/helpers/mongodb.rb +59 -0
  31. data/spec/helpers/truncate.rb +15 -0
  32. data/spec/monga/collection_spec.rb +448 -0
  33. data/spec/monga/connection_pool_spec.rb +50 -0
  34. data/spec/monga/connection_spec.rb +64 -0
  35. data/spec/monga/cursor_spec.rb +186 -0
  36. data/spec/monga/database_spec.rb +67 -0
  37. data/spec/monga/replica_set_client_spec.rb +46 -0
  38. data/spec/monga/requests/delete_spec.rb +0 -0
  39. data/spec/monga/requests/insert_spec.rb +0 -0
  40. data/spec/monga/requests/query_spec.rb +28 -0
  41. data/spec/spec_helper.rb +29 -0
  42. metadata +185 -0
data/monga.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "monga"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["Petr Yanovich"]
9
+ spec.email = ["fl00r@yandex.ru"]
10
+ spec.description = %q{MongoDB Ruby Evented Driver on EventMachine}
11
+ spec.summary = %q{MongoDB Ruby Evented Driver on EventMachine}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.3"
21
+ spec.add_development_dependency "rake"
22
+
23
+ spec.add_dependency "eventmachine"
24
+ spec.add_dependency "bson"
25
+ spec.add_dependency "bson_ext"
26
+ end
@@ -0,0 +1,59 @@
1
+ module Mongodb
2
+ MONGOD_PATH = "mongod"
3
+
4
+ class Instance
5
+ def initialize(opts)
6
+ @opts = opts
7
+ @cmd = [MONGOD_PATH]
8
+ opts.each do |k,v|
9
+ @cmd << "--#{k}"
10
+ @cmd << v.to_s
11
+ end
12
+ clean_lock
13
+ shtdwn
14
+ start
15
+ end
16
+
17
+ def clean_lock
18
+ lock = @opts[:dbpath] + "/mongod.lock"
19
+ File.rm(lock)
20
+ rescue
21
+ # ok
22
+ end
23
+
24
+ def shtdwn
25
+ system "#{@cmd * ' '} --shutdown"
26
+ end
27
+
28
+ def start
29
+ return @pid if @pid
30
+ @pid = spawn(*@cmd, out: "/dev/null")
31
+ sleep(1)
32
+ end
33
+
34
+ def stop
35
+ return unless @pid
36
+ Process.kill("SIGINT", @pid)
37
+ Process.waitpid(@pid)
38
+ @pid = nil
39
+ end
40
+ end
41
+
42
+ class ReplicaSet
43
+ def initialize(ports, opts={})
44
+ opts[:replSet] ||= "rs1"
45
+ opts[:dbpath] ||= "/tmp/mongodb/rs0"
46
+ @instances = {}
47
+ ports.each.with_index do |prt, i|
48
+ dbpath = opts[:dbpath] + "-#{i}"
49
+ o = opts.merge({ port: prt[:port], dbpath: dbpath })
50
+ @instances[prt[:port]] = Instance.new(o)
51
+ end
52
+ end
53
+
54
+ def primary
55
+ pr = RS_CLIENT.primary
56
+ @instances[pr.aquire_connection.port] if pr
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,15 @@
1
+ module Helpers
2
+ module Truncate
3
+ def teardown
4
+ EM.run do
5
+ RS_COLLECTION.safe_delete.callback do
6
+ RS_COLLECTION.drop_indexes.callback do
7
+ COLLECTION.safe_delete.callback do |res|
8
+ COLLECTION.drop_indexes.callback{ EM.stop }
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,448 @@
1
+ require 'spec_helper'
2
+
3
+ describe Monga::Collection do
4
+ include Helpers::Truncate
5
+
6
+ describe "queries" do
7
+ before do
8
+ EM.run do
9
+ req = COLLECTION.safe_insert([
10
+ { author: "Madonna", title: "Burning Up" },
11
+ { author: "Madonna", title: "Freezing" },
12
+ { author: "Madonna", title: "Untitled Track 1" },
13
+ { author: "Madonna", title: "Untitled Track 2" },
14
+ { author: "Madonna", title: "Untitled Track 3" },
15
+ { author: "Madonna", title: "Untitled Track 4" },
16
+ { author: "Madonna", title: "Untitled Track 5" },
17
+ { author: "Radiohead", title: "Karma Police" },
18
+ ])
19
+ req.callback{ EM.stop }
20
+ req.errback{ |err| raise err }
21
+ end
22
+ end
23
+
24
+ it "should find all" do
25
+ EM.run do
26
+ req = COLLECTION.find
27
+ req.callback do |data|
28
+ data.size.must_equal 8
29
+ data.first.tap{|d| d.delete "_id" }.must_equal({ "author" => "Madonna", "title" => "Burning Up" })
30
+ EM.stop
31
+ end
32
+ req.errback{ |err| raise err }
33
+ end
34
+ end
35
+
36
+ it "should findOne aka first" do
37
+ EM.run do
38
+ req = COLLECTION.first
39
+ req.callback do |data|
40
+ data.tap{|d| d.delete "_id" }.must_equal({ "author" => "Madonna", "title" => "Burning Up" })
41
+ EM.stop
42
+ end
43
+ req.errback{ |err| raise err }
44
+ end
45
+ end
46
+
47
+ it "should find limit" do
48
+ EM.run do
49
+ req = COLLECTION.find.limit(2)
50
+ req.callback do |data|
51
+ data.size.must_equal 2
52
+ data.first.tap{|d| d.delete "_id" }.must_equal({ "author" => "Madonna", "title" => "Burning Up" })
53
+ EM.stop
54
+ end
55
+ req.errback{ |err| raise err }
56
+ end
57
+ end
58
+
59
+ it "should find skip" do
60
+ EM.run do
61
+ req = COLLECTION.find.limit(3).skip(2)
62
+ req.callback do |data|
63
+ data.size.must_equal 3
64
+ data.first.tap{|d| d.delete "_id" }.must_equal({ "author" => "Madonna", "title" => "Untitled Track 1" })
65
+ EM.stop
66
+ end
67
+ req.errback{ |err| raise err }
68
+ end
69
+ end
70
+
71
+ it "should find with batch_size" do
72
+ EM.run do
73
+ cursor = COLLECTION.find.batch_size(2).cursor
74
+ req = cursor.send(:next_batch)
75
+ req.callback do |batch|
76
+ batch.size.must_equal 2
77
+ batch.first.tap{|d| d.delete "_id" }.must_equal({ "author" => "Madonna", "title" => "Burning Up" })
78
+ EM.stop
79
+ end
80
+ req.errback{ |err| raise err }
81
+ end
82
+ end
83
+
84
+ it "should return next document" do
85
+ EM.run do
86
+ cursor = COLLECTION.find.batch_size(2).cursor
87
+ req = cursor.next_document
88
+ req.callback do |doc|
89
+ doc.tap{|d| d.delete "_id" }.must_equal({ "author" => "Madonna", "title" => "Burning Up" })
90
+ EM.stop
91
+ end
92
+ req.errback{ |err| raise err }
93
+ end
94
+ end
95
+
96
+ it "should find with skip limit and query" do
97
+ EM.run do
98
+ req = COLLECTION.find(author: "Madonna").limit(10).skip(2)
99
+ req.callback do |data|
100
+ data.size.must_equal 5
101
+ data.first.tap{|d| d.delete "_id" }.must_equal({ "author" => "Madonna", "title" => "Untitled Track 1" })
102
+ EM.stop
103
+ end
104
+ req.errback{ |err| raise err }
105
+ end
106
+ end
107
+
108
+ it "should return nothing" do
109
+ EM.run do
110
+ req = COLLECTION.find(author: "Bjork")
111
+ req.callback do |data|
112
+ data.size.must_equal 0
113
+ EM.stop
114
+ end
115
+ req.errback{ |err| raise err }
116
+ end
117
+ end
118
+
119
+ it "should return specific fields" do
120
+ EM.run do
121
+ req = COLLECTION.find({author: "Madonna"}, { author: 1 })
122
+ req.callback do |data|
123
+ data.size.must_equal 7
124
+ p data.map(&:keys).flatten.uniq.must_equal(["_id", "author"])
125
+ EM.stop
126
+ end
127
+ req.errback{ |err| raise err }
128
+ end
129
+ end
130
+ end
131
+
132
+ describe "tailable cursor" do
133
+ before do
134
+ EM.run do
135
+ CAPPED_COLLECTION = DB["cappedCollection"]
136
+ req = DB.create_collection("cappedCollection", capped: true, size: 10*1024)
137
+ req.callback do
138
+ CAPPED_COLLECTION.safe_insert([
139
+ {title: "Doc 1"},
140
+ {title: "Doc 2"},
141
+ {title: "Doc 3"},
142
+ ]).callback do
143
+ EM.stop
144
+ end
145
+ end
146
+ req.errback{ |err| p err; EM.stop }
147
+ end
148
+ end
149
+
150
+ after do
151
+ EM.run do
152
+ DB.drop_collection("cappedCollection").callback do
153
+ EM.stop
154
+ end
155
+ end
156
+ end
157
+
158
+ it "should return tailable cursor" do
159
+ EM.run do
160
+ cursor = CAPPED_COLLECTION.find.cursor(tailable_cursor: true)
161
+ cursor.each_doc{ p "do nothing" }
162
+ cursor.callback do
163
+ req = CAPPED_COLLECTION.safe_insert({ title: "Last One" })
164
+ req.callback do
165
+ cursor.next_document.callback do |doc|
166
+ doc["title"].must_equal "Last One"
167
+ cursor.kill
168
+ CAPPED_COLLECTION.safe_insert({ title: "The Very Last One" }).callback do
169
+ cursor.next_document.errback do |err|
170
+ err.class.must_equal Monga::Exceptions::CursorIsClosed
171
+ EM.stop
172
+ end
173
+ end
174
+ end
175
+ end
176
+ req.errback{ |err| p ["err", err]}
177
+ end
178
+ cursor.errback{ |err| p ["err", err ]}
179
+ end
180
+ end
181
+ end
182
+
183
+ describe "fetch many data" do
184
+ before do
185
+ MANY = 1000
186
+ EM.run do
187
+ req = COLLECTION.safe_insert(
188
+ MANY.times.map{ |i| { row: (i+1).to_s } }
189
+ )
190
+ req.callback{ EM.stop }
191
+ req.errback{ |err| raise err }
192
+ end
193
+ end
194
+
195
+ it "should fetch em all and count" do
196
+ EM.run do
197
+ req = COLLECTION.find
198
+ req.callback do |docs|
199
+ docs.size.must_equal MANY
200
+ COLLECTION.count.callback do |c|
201
+ c.must_equal MANY
202
+ EM.stop
203
+ end
204
+ end
205
+ req.errback{ |err| raise err }
206
+ end
207
+ end
208
+ end
209
+
210
+ describe "insert" do
211
+ it "should single insert" do
212
+ EM.run do
213
+ COLLECTION.insert(todo: "shopping")
214
+ EM.add_timer(0.05) do
215
+ req = COLLECTION.first
216
+ req.callback do |resp|
217
+ resp["todo"].must_equal "shopping"
218
+ EM.stop
219
+ end
220
+ req.errback{ |err| raise err }
221
+ end
222
+ end
223
+ end
224
+
225
+ it "should safe_insert" do
226
+ EM.run do
227
+ req = COLLECTION.safe_insert(todo: "shopping")
228
+ req.callback do
229
+ req = COLLECTION.first
230
+ req.callback do |resp|
231
+ resp["todo"].must_equal "shopping"
232
+ EM.stop
233
+ end
234
+ req.errback{ |err| raise err }
235
+ end
236
+ req.errback{ |err| raise err }
237
+ end
238
+ end
239
+
240
+ it "should batch insert" do
241
+ EM.run do
242
+ req = COLLECTION.safe_insert([{todo: "shopping"}, {todo: "walking"}, {todo: "dinner with Scarlett"}])
243
+ req.callback do
244
+ req = COLLECTION.find
245
+ req.callback do |resp|
246
+ resp.size.must_equal 3
247
+ resp.map{|r| r["todo"]}.must_equal ["shopping", "walking", "dinner with Scarlett"]
248
+ EM.stop
249
+ end
250
+ req.errback{ |err| raise err }
251
+ end
252
+ req.errback{ |err| raise err }
253
+ end
254
+ end
255
+
256
+ it "should fail on uniq index" do
257
+ EM.run do
258
+ COLLECTION.ensure_index({book_id: 1}, {unique: true})
259
+ req = COLLECTION.safe_insert([{book_id: 1, title: "Bible"}, {book_id: 1, title: "Lord of the Ring"}, {book_id: 2, title: "War and Piece"}, {book_id: 3, title: "Harry Potter"}])
260
+ req.callback do
261
+ fail "It should never happen"
262
+ end
263
+ req.errback do |err|
264
+ err.class.must_equal Monga::Exceptions::QueryFailure
265
+ COLLECTION.count.callback do |n|
266
+ n.must_equal 1
267
+ EM.stop
268
+ end
269
+ end
270
+ end
271
+ end
272
+
273
+ it "should continue to insert if error happend" do
274
+ EM.run do
275
+ COLLECTION.ensure_index({book_id: 1}, {unique: true})
276
+ req = COLLECTION.safe_insert([{book_id: 1, title: "Bible"}, {book_id: 1, title: "Lord of the Ring"}, {book_id: 2, title: "War and Piece"}, {book_id: 3, title: "Harry Potter"}], {continue_on_error: true})
277
+ req.callback do |res|
278
+ fail "It should never happen"
279
+ end
280
+ req.errback do |err|
281
+ COLLECTION.count.callback do |n|
282
+ n.must_equal 3
283
+ EM.stop
284
+ end
285
+ end
286
+ end
287
+ end
288
+ end
289
+
290
+ describe "indexes" do
291
+ it "should create an index" do
292
+ EM.run do
293
+ COLLECTION.ensure_index(artist: 1)
294
+ req = COLLECTION.get_indexes
295
+ req.callback do |indexes|
296
+ indexes.any?{ |ind| ind["ns"] == "#{DB.name}.#{COLLECTION.name}" && ind["key"] == {"artist" => 1}}.must_equal true
297
+ EM.stop
298
+ end
299
+ req.errback{ |err| raise err }
300
+ end
301
+ end
302
+
303
+ it "should drop an index" do
304
+ EM.run do
305
+ COLLECTION.ensure_index(artist: 1)
306
+ req = COLLECTION.drop_index(artist: 1)
307
+ req.callback do |resp|
308
+ req = COLLECTION.get_indexes
309
+ req.callback do |indexes|
310
+ indexes.any?{ |ind| ind["ns"] == "#{DB.name}.#{COLLECTION.name}" && ind["key"] == {"artist" => 1}}.must_equal false
311
+ EM.stop
312
+ end
313
+ req.errback{ |err| raise err }
314
+ end
315
+ req.errback{ |err| raise err }
316
+ end
317
+ end
318
+
319
+ it "should create unique index" do
320
+ EM.run do
321
+ COLLECTION.ensure_index({artist: 1}, {unique: 1})
322
+ req = COLLECTION.get_indexes
323
+ req.callback do |indexes|
324
+ indexes.any?{ |ind| ind["ns"] == "#{DB.name}.#{COLLECTION.name}" && ind["key"] == {"artist" => 1} && ind["unique"] == true}.must_equal true
325
+ EM.stop
326
+ end
327
+ req.errback{ |err| raise err }
328
+ end
329
+ end
330
+
331
+ # Why somebody needs to do safe_ensure_index?
332
+ it "should not fail on safe_ensure_index" do
333
+ EM.run do
334
+ req = COLLECTION.safe_ensure_index({artist: 1}, {unique: 1})
335
+ req.callback do |res|
336
+ req.callback{ |res| EM.stop }
337
+ req.errback{ |err| raise err }
338
+ end
339
+ req.errback{ |err| raise err }
340
+ end
341
+ end
342
+ end
343
+
344
+ describe "update" do
345
+ before do
346
+ EM.run do
347
+ COLLECTION.safe_insert([
348
+ { artist: "Madonna", title: "Burning Up", status: "Out of Order" },
349
+ { artist: "Madonna", title: "Freezing", status: "Out of Order" }
350
+ ]).callback{ EM.stop }
351
+ end
352
+ end
353
+
354
+ it "should update exist item (first matching)" do
355
+ EM.run do
356
+ req = COLLECTION.safe_update({artist: "Madonna"}, {artist: "Madonna", status: "Available"})
357
+ req.callback do |res|
358
+ COLLECTION.find.callback do |docs|
359
+ d = docs.first
360
+ d.delete("_id")
361
+ d.must_equal({"artist" => "Madonna", "status" => "Available"})
362
+ docs.last["status"].must_equal "Out of Order"
363
+ EM.stop
364
+ end
365
+ end
366
+ end
367
+ end
368
+
369
+ it "should update exist item (all matching, multi_update)" do
370
+ EM.run do
371
+ req = COLLECTION.safe_update({artist: "Madonna"}, {"$set" => { status: "Available"}}, {multi_update: true})
372
+ req.callback do |res|
373
+ COLLECTION.find.callback do |docs|
374
+ docs.map{|d| [d["artist"], d["status"]]}.must_equal([["Madonna", "Available"], ["Madonna", "Available"]])
375
+ EM.stop
376
+ end
377
+ end
378
+ req.errback{ |err| raise err }
379
+ end
380
+ end
381
+
382
+ it "should do nothing on update non existing item" do
383
+ EM.run do
384
+ req = COLLECTION.safe_update({artist: "Madonna2"}, {status: "Available"})
385
+ req.callback do |res|
386
+ req = COLLECTION.find(artist: "Madonna2").callback do |docs|
387
+ docs.size.must_equal 0
388
+ EM.stop
389
+ end
390
+ end
391
+ req.errback do |err|
392
+ raise err
393
+ end
394
+ end
395
+ end
396
+
397
+ it "should create non existing item (upsert)" do
398
+ EM.run do
399
+ req = COLLECTION.safe_update({artist: "Madonna2"}, {"$set" => {status: "Available"}}, {upsert: true})
400
+ req.callback do |res|
401
+ req = COLLECTION.find(artist: "Madonna2").callback do |docs|
402
+ docs.size.must_equal 1
403
+ docs.first["artist"].must_equal("Madonna2")
404
+ docs.first["status"].must_equal("Available")
405
+ EM.stop
406
+ end
407
+ end
408
+ req.errback do |err|
409
+ raise err
410
+ end
411
+ end
412
+ end
413
+ end
414
+
415
+ describe "DELETE OP" do
416
+ before do
417
+ EM.run do
418
+ COLLECTION.safe_insert([
419
+ { artist: "Madonna", title: "Burning Up", status: "Out of Order" },
420
+ { artist: "Madonna", title: "Freezing", status: "Out of Order" }
421
+ ]).callback{ EM.stop }
422
+ end
423
+ end
424
+
425
+ it "should delete all docs" do
426
+ EM.run do
427
+ COLLECTION.safe_delete(artist: "Madonna").callback do
428
+ COLLECTION.count.callback do |n|
429
+ n.must_equal 0
430
+ EM.stop
431
+ end
432
+ end
433
+ end
434
+ end
435
+
436
+ it "should delete first matching" do
437
+ EM.run do
438
+ COLLECTION.safe_delete({artist: "Madonna"}, {single_remove: true}).callback do
439
+ COLLECTION.find.callback do |docs|
440
+ docs.size.must_equal 1
441
+ docs.first["title"].must_equal "Freezing"
442
+ EM.stop
443
+ end
444
+ end
445
+ end
446
+ end
447
+ end
448
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe Monga::ConnectionPool do
4
+ # include Helpers::Truncate
5
+ before do
6
+ INSTANCE.start
7
+ EM.run do
8
+ @client = Monga::Client.new(pool_size: 2)
9
+ @db = @client["dbTest"]
10
+ @collection = @db["testCollection"]
11
+ EM.stop
12
+ end
13
+ end
14
+
15
+ it "should aquire connections correctly" do
16
+ EM.run do
17
+ conns = []
18
+ req = @collection.safe_insert(artist: "Madonna")
19
+ EM.next_tick do
20
+ 100.times do
21
+ conns << @client.aquire_connection
22
+ end
23
+ conns.uniq.size.must_equal 1
24
+ req.callback do
25
+ 100.times{ conns << @client.aquire_connection }
26
+ conns.uniq.size.must_equal 2
27
+ EM.stop
28
+ end
29
+ req.errback{ |err| raise err }
30
+ end
31
+ end
32
+ end
33
+
34
+ it "should aquire connections correctly when there are waiting responses on each connection" do
35
+ EM.run do
36
+ conns = []
37
+ @client.connection_pool.connections.each(&:connected?)
38
+ EM.next_tick do
39
+ @collection.safe_insert(artist: "Madonna")
40
+ @collection.safe_insert(artist: "Madonna")
41
+ 100.times do
42
+ conns << @client.aquire_connection
43
+ end
44
+ conns.uniq.size.must_equal 2
45
+ @client.connection_pool.connections.all?{|c| c.responses.size == 1}.must_equal true
46
+ EM.stop
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe Monga::Connection do
4
+ describe "One instance" do
5
+ it "should try to connect to stopped instance then instance is started and connection became connected" do
6
+ EM.run do
7
+ INSTANCE.stop
8
+ connection = Monga::Client.new( host: "localhost", port: 27017 )
9
+ EM.next_tick do
10
+ connection.connected?.must_equal false
11
+ INSTANCE.start
12
+ EM.add_timer(0.5) do
13
+ connection.connected?.must_equal true
14
+ EM.stop
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ it "should retrieve connection after restarting of EventMacine" do
21
+ INSTANCE.start
22
+ connection = nil
23
+ EM.run do
24
+ connection = Monga::Client.new( host: "localhost", port: 27017 )
25
+ EM.next_tick do
26
+ connection.connected?.must_equal true
27
+ EM.stop
28
+ end
29
+ end
30
+ connection.connected?.must_equal false
31
+ EM.run do
32
+ # Somebody tries to send data
33
+ # Driver should automatically reconnect
34
+ connection["dbTest"].get_last_error
35
+ EM.add_timer(0.1) do
36
+ connection.connected?.must_equal true
37
+ EM.next_tick{ EM.stop }
38
+ end
39
+ end
40
+ end
41
+
42
+ it "should receive errback while trying to fetch data from stopped mongo" do
43
+ EM.run do
44
+ connection = Monga::Client.new( host: "localhost", port: 27017 )
45
+ INSTANCE.stop
46
+ req = connection["dbTest"].get_last_error
47
+ req.callback{ |r| puts "never executed" }
48
+ req.errback do |err|
49
+ err.class.must_equal Monga::Exceptions::LostConnection
50
+ EM.stop
51
+ end
52
+ end
53
+ INSTANCE.start
54
+ end
55
+ end
56
+
57
+ describe "Replica Set connection" do
58
+ # TODO
59
+ end
60
+
61
+ describe "Master Slave connection" do
62
+ # TODO
63
+ end
64
+ end