monga 0.0.2 → 0.0.3

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