monga 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 (63) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +1 -0
  3. data/README.md +59 -3
  4. data/lib/monga/client.rb +51 -6
  5. data/lib/monga/clients/master_slave_client.rb +0 -5
  6. data/lib/monga/clients/replica_set_client.rb +32 -71
  7. data/lib/monga/clients/single_instance_client.rb +53 -0
  8. data/lib/monga/collection.rb +102 -41
  9. data/lib/monga/connection.rb +38 -13
  10. data/lib/monga/connection_pool.rb +6 -17
  11. data/lib/monga/connections/buffer.rb +33 -0
  12. data/lib/monga/connections/em_connection.rb +25 -56
  13. data/lib/monga/connections/em_proxy_connection.rb +80 -0
  14. data/lib/monga/connections/fibered_connection.rb +26 -0
  15. data/lib/monga/connections/fibered_proxy_connection.rb +23 -0
  16. data/lib/monga/connections/proxy_connection.rb +4 -0
  17. data/lib/monga/connections/tcp_connection.rb +57 -0
  18. data/lib/monga/cursor.rb +197 -95
  19. data/lib/monga/database.rb +175 -60
  20. data/lib/monga/{requests → protocol}/delete.rb +1 -2
  21. data/lib/monga/{requests → protocol}/get_more.rb +1 -1
  22. data/lib/monga/{requests → protocol}/insert.rb +1 -2
  23. data/lib/monga/{requests → protocol}/kill_cursors.rb +1 -1
  24. data/lib/monga/{requests → protocol}/query.rb +3 -3
  25. data/lib/monga/{requests → protocol}/update.rb +1 -1
  26. data/lib/monga/request.rb +27 -23
  27. data/lib/monga/utils/constants.rb +5 -0
  28. data/lib/monga/utils/exceptions.rb +11 -0
  29. data/lib/monga.rb +19 -11
  30. data/monga.gemspec +2 -2
  31. data/spec/helpers/mongodb.rb +115 -38
  32. data/spec/monga/block/collection_spec.rb +172 -0
  33. data/spec/monga/block/cursor_spec.rb +160 -0
  34. data/spec/monga/block/database_spec.rb +80 -0
  35. data/spec/monga/block/single_instance_client_spec.rb +31 -0
  36. data/spec/monga/em/collection_spec.rb +308 -0
  37. data/spec/monga/em/cursor_spec.rb +256 -0
  38. data/spec/monga/em/database_spec.rb +140 -0
  39. data/spec/monga/em/replica_set_client_spec.rb +86 -0
  40. data/spec/monga/em/single_instance_client_spec.rb +28 -0
  41. data/spec/monga/sync/collection_spec.rb +247 -0
  42. data/spec/monga/sync/cursor_spec.rb +211 -0
  43. data/spec/monga/sync/database_spec.rb +110 -0
  44. data/spec/monga/sync/replica_set_client_spec.rb +54 -0
  45. data/spec/monga/sync/single_instance_client_spec.rb +25 -0
  46. data/spec/spec_helper.rb +2 -20
  47. metadata +50 -38
  48. data/lib/monga/clients/client.rb +0 -24
  49. data/lib/monga/connections/primary.rb +0 -46
  50. data/lib/monga/connections/secondary.rb +0 -13
  51. data/lib/monga/exceptions.rb +0 -9
  52. data/lib/monga/miner.rb +0 -72
  53. data/lib/monga/response.rb +0 -11
  54. data/spec/helpers/truncate.rb +0 -15
  55. data/spec/monga/collection_spec.rb +0 -448
  56. data/spec/monga/connection_pool_spec.rb +0 -50
  57. data/spec/monga/connection_spec.rb +0 -64
  58. data/spec/monga/cursor_spec.rb +0 -186
  59. data/spec/monga/database_spec.rb +0 -67
  60. data/spec/monga/replica_set_client_spec.rb +0 -46
  61. data/spec/monga/requests/delete_spec.rb +0 -0
  62. data/spec/monga/requests/insert_spec.rb +0 -0
  63. data/spec/monga/requests/query_spec.rb +0 -28
@@ -1,448 +0,0 @@
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
@@ -1,50 +0,0 @@
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
@@ -1,64 +0,0 @@
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