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
@@ -0,0 +1,160 @@
1
+ require 'spec_helper'
2
+
3
+ describe Monga::Cursor do
4
+ before do
5
+ @client = Monga::Client.new(type: :block, pool_size: 10)
6
+ @db = @client["dbTest"]
7
+ @collection = @db["testCollection"]
8
+ @collection.safe_remove
9
+ docs = []
10
+ 10.times do |i|
11
+ docs << { artist: "Madonna", title: "Track #{i+1}" }
12
+ docs << { artist: "Radiohead", title: "Track #{i+1}" }
13
+ end
14
+ @collection.safe_insert(docs)
15
+ end
16
+
17
+ # ALL
18
+
19
+ describe "all" do
20
+ it "should find all" do
21
+ docs = @collection.find.all
22
+ docs.size.must_equal 20
23
+ end
24
+
25
+ it "should find all with query" do
26
+ docs = @collection.find(artist: "Madonna").all
27
+ docs.size.must_equal 10
28
+ docs.each{ |d| d["artist"].must_equal "Madonna" }
29
+ end
30
+
31
+ it "should find all with limit" do
32
+ docs = @collection.find.limit(5).all
33
+ docs.size.must_equal 5
34
+ end
35
+
36
+ it "should find all with batch size" do
37
+ docs = @collection.find.batch_size(2).all
38
+ docs.size.must_equal 20
39
+ end
40
+
41
+ it "should find all with skip" do
42
+ docs = @collection.find.skip(10).all
43
+ docs.size.must_equal 10
44
+ end
45
+ end
46
+
47
+ # FIRST
48
+
49
+ describe "first" do
50
+ it "should fetch first with sort" do
51
+ doc = @collection.find.sort(title: 1).first
52
+ doc["title"].must_equal "Track 1"
53
+ end
54
+
55
+ it "should fetch first with sort and skip" do
56
+ doc = @collection.find.sort(title: 1).skip(2).first
57
+ doc["title"].must_equal "Track 10"
58
+ end
59
+ end
60
+
61
+ # NEXT_BATCH
62
+
63
+ describe "next_batch" do
64
+ it "should fetch batches" do
65
+ cursor = @collection.find.batch_size(2).limit(3)
66
+ batch, more = cursor.next_batch
67
+ batch.size.must_equal 2
68
+ more.must_equal true
69
+ batch, more = cursor.next_batch
70
+ batch.size.must_equal 1
71
+ more.must_equal false
72
+ end
73
+ end
74
+
75
+ # EACH_BATCH
76
+
77
+ describe "each_batch" do
78
+ it "should fetch 3 items by batches" do
79
+ docs = []
80
+ @collection.find.batch_size(2).limit(3).each_batch do |batch|
81
+ docs += batch
82
+ end
83
+ docs.size.must_equal 3
84
+ end
85
+ end
86
+
87
+ # NEXT_DOC
88
+
89
+ describe "next_doc" do
90
+ it "should fetch doc by doc" do
91
+ cursor = @collection.find.limit(3).batch_size(2)
92
+ doc, more = cursor.next_doc
93
+ more.must_equal true
94
+ doc, more = cursor.next_doc
95
+ doc, more = cursor.next_doc
96
+ more.must_equal false
97
+ end
98
+ end
99
+
100
+ # # EACH_DOC
101
+
102
+ describe "each_doc" do
103
+ it "should iterate over some docs" do
104
+ docs = []
105
+ @collection.find.limit(100).skip(15).batch_size(3).each_doc do |doc|
106
+ docs << doc
107
+ end
108
+ docs.size.must_equal 5
109
+ end
110
+
111
+ it "should iterate over all docs" do
112
+ docs = []
113
+ @collection.find.batch_size(3).each_doc do |doc|
114
+ docs << doc
115
+ end
116
+ docs.size.must_equal 20
117
+ end
118
+ end
119
+
120
+ # KILL CURSOR
121
+
122
+ describe "kill" do
123
+ it "should work with kill" do
124
+ cursor = @collection.find
125
+ batch, more = cursor.next_batch
126
+ cursor.kill
127
+ proc{ cursor.next_batch }.must_raise Monga::Exceptions::ClosedCursor
128
+ end
129
+ end
130
+
131
+ # TAILABLE CURSOR
132
+
133
+ describe "tailable cursor" do
134
+ before do
135
+ @db.create_collection("testCapped", capped: true, size: 4*1024)
136
+ @capped = @db["testCapped"]
137
+ @capped.safe_insert(title: "Test")
138
+ end
139
+
140
+ after do
141
+ @db["testCapped"].drop
142
+ end
143
+
144
+ it "should be tailable" do
145
+ tailable_cursor = @capped.find.flag(tailable_cursor: true)
146
+ docs = []
147
+ tailable_cursor.each_doc do |doc|
148
+ @capped.insert(title: "New!")
149
+ if doc
150
+ docs << doc
151
+ if docs.size == 2
152
+ docs.map{ |d| d["title"] }.must_equal ["Test", "New!"]
153
+ break
154
+ end
155
+ end
156
+ end
157
+ tailable_cursor.kill
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe Monga::Database do
4
+ before do
5
+ @client = Monga::Client.new
6
+ @db = @client["dbTest"]
7
+ @collection = @db["testCollection"]
8
+ @collection.safe_remove
9
+ end
10
+
11
+ after do
12
+ @collection.safe_remove
13
+ end
14
+
15
+ it "should create and drop collection" do
16
+ @db.create_collection("cappedCollection")
17
+ @db.list_collections["retval"].must_include "cappedCollection"
18
+ @db.drop_collection("cappedCollection")
19
+ @db.list_collections["retval"].wont_include "cappedCollection"
20
+ end
21
+
22
+ it "should count in collection" do
23
+ @collection.safe_insert([{ title: 1 }, { title: 2 }])
24
+ @db.count("testCollection").must_equal 2
25
+ end
26
+
27
+ it "should eval javascript" do
28
+ @db.eval("1+1")["retval"].must_equal 2.0
29
+ end
30
+
31
+ # INDEXES
32
+
33
+ describe "indexes" do
34
+ before do
35
+ @db.drop_indexes("testCollection", "*")
36
+ end
37
+
38
+ it "should drop index" do
39
+ @collection.safe_ensure_index(title: 1)
40
+ @collection.get_indexes.select{ |i| i["ns"] == "dbTest.testCollection" }.size.must_equal 2
41
+ @db.drop_indexes("testCollection", title: 1)
42
+ @collection.get_indexes.select{ |i| i["ns"] == "dbTest.testCollection" }.size.must_equal 1
43
+ end
44
+ end
45
+
46
+ # GET LAST ERROR
47
+
48
+ describe "getLastError" do
49
+ before do
50
+ @collection.drop_indexes
51
+ @collection.safe_ensure_index({ personal_id: 1 }, { unique: true, sparse: true })
52
+ end
53
+
54
+ it "should get last error" do
55
+ req = @collection.insert(name: "Peter", personal_id: 10)
56
+ @db.get_last_error(req.connection)["ok"].must_equal 1.0
57
+ req = @collection.insert(name: "Peter", personal_id: 10)
58
+ @db.get_last_error(req.connection).class.must_equal Monga::Exceptions::QueryFailure
59
+ end
60
+
61
+ it "should getLastError with fsync" do
62
+ req = @collection.insert(name: "Peter", personal_id: 10)
63
+ @db.get_last_error(req.connection, fsync: true)["ok"].must_equal 1.0
64
+ req = @collection.insert(name: "Peter", personal_id: 10)
65
+ @db.get_last_error(req.connection, fsync: true).class.must_equal Monga::Exceptions::QueryFailure
66
+ end
67
+ end
68
+
69
+ # AGGREGATION
70
+
71
+ describe "aggregation" do
72
+ it "should aggregate"
73
+ end
74
+
75
+ # MAP REDUCE
76
+
77
+ describe "map reduce" do
78
+ it "should run map reduce"
79
+ end
80
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Monga::Clients::SingleInstanceClient do
4
+ before do
5
+ EM.synchrony do
6
+ @client = Monga::Client.new port: 29000, type: :block
7
+ @collection = @client["dbTest"]["myCollection"]
8
+ @instance = Fake::SingleInstance.new(29000)
9
+ EM.stop
10
+ end
11
+ @t = Thread.new do
12
+ EM.run do
13
+ @instance.start
14
+ end
15
+ end
16
+ end
17
+
18
+ after do
19
+ EM.stop
20
+ @t.join
21
+ end
22
+
23
+ it "should fail on disconnect and reconnect when instance is up again" do
24
+ @collection.safe_insert(name: "Peter")
25
+ @instance.stop
26
+ proc{ @collection.safe_insert(name: "Peter") }.must_raise Monga::Exceptions::Disconnected
27
+ proc{ @collection.safe_insert(name: "Peter") }.must_raise Monga::Exceptions::Disconnected
28
+ @instance.start
29
+ @collection.safe_insert(name: "Madonna")
30
+ end
31
+ end
@@ -0,0 +1,308 @@
1
+ require 'spec_helper'
2
+
3
+ describe Monga::Collection do
4
+ before do
5
+ EM.run do
6
+ @client = Monga::Client.new(type: :em, pool_size: 10)
7
+ @db = @client["dbTest"]
8
+ @collection = @db["testCollection"]
9
+ @collection.safe_remove do |err, resp|
10
+ raise err if err
11
+ docs = []
12
+ 10.times do |i|
13
+ docs << { artist: "Madonna", title: "Track #{i+1}" }
14
+ docs << { artist: "Radiohead", title: "Track #{i+1}" }
15
+ end
16
+ @collection.safe_insert(docs) do |err|
17
+ raise err if err
18
+ EM.stop
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ # QUERY
25
+
26
+ describe "query" do
27
+ it "should fetch all documents" do
28
+ EM.run do
29
+ @collection.find.all do |err, docs|
30
+ docs.size.must_equal 20
31
+ EM.stop
32
+ end
33
+ end
34
+ end
35
+
36
+ it "should fetch all docs with skip and limit" do
37
+ EM.run do
38
+ @collection.find.skip(10).limit(4).all do |err, docs|
39
+ docs.size.must_equal 4
40
+ EM.stop
41
+ end
42
+ end
43
+ end
44
+
45
+ it "should fetch first" do
46
+ EM.run do
47
+ @collection.first do |err, doc|
48
+ doc.keys.must_equal ["_id", "artist", "title"]
49
+ EM.stop
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ # INSERT
56
+
57
+ describe "insert" do
58
+ before do
59
+ EM.run do
60
+ @collection.safe_ensure_index({ "personal_id" => 1 }, { unique: true, sparse: true }) do |err, resp|
61
+ raise err if err
62
+ EM.stop
63
+ end
64
+ end
65
+ end
66
+
67
+ after do
68
+ EM.run do
69
+ @collection.drop_index( personal_id: 1 ) do |err, resp|
70
+ raise err if err
71
+ EM.stop
72
+ end
73
+ end
74
+ end
75
+
76
+ it "should insert single doc" do
77
+ EM.run do
78
+ doc = { name: "Peter", age: 18 }
79
+ @collection.safe_insert(doc) do |err, resp|
80
+ @collection.find(name: "Peter").all do |err, resp|
81
+ resp.size.must_equal 1
82
+ resp.first["age"].must_equal 18
83
+ EM.stop
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ it "should insert batch of docs" do
90
+ EM.run do
91
+ docs = [{ name: "Peter", age: 18 }, {name: "Jhon", age: 18}]
92
+ @collection.safe_insert(docs) do |err, resp|
93
+ @collection.find(age: 18).all do |err, resp|
94
+ resp.size.must_equal 2
95
+ EM.stop
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ it "should fail on uniq index" do
102
+ EM.run do
103
+ docs = [{ name: "Peter", age: 18, personal_id: 20 }, {name: "Jhon", age: 18, personal_id: 20}, {name: "Rebeca", age: 21, personal_id: 5}]
104
+ @collection.safe_insert(docs) do |err, resp|
105
+ (Monga::Exceptions::QueryFailure === err).must_equal true
106
+ @collection.count do |err, cnt|
107
+ cnt.must_equal 21
108
+ EM.stop
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ it "should continue_on_error" do
115
+ EM.run do
116
+ docs = [{ name: "Peter", age: 18, personal_id: 20 }, {name: "Jhon", age: 18, personal_id: 20}, {name: "Rebeca", age: 21, personal_id: 5}]
117
+ @collection.safe_insert(docs, continue_on_error: true) do |err, resp|
118
+ (Monga::Exceptions::QueryFailure === err).must_equal true
119
+ @collection.count do |err, cnt|
120
+ cnt.must_equal 22
121
+ EM.stop
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ # UPDATE
129
+
130
+ describe "update" do
131
+ it "should make simple update (first matching)" do
132
+ EM.run do
133
+ @collection.safe_update({ artist: "Madonna" }, { "$set" => { country: "USA" } }) do |err, resp|
134
+ @collection.count( query: { artist: "Madonna", country: "USA" }) do |err, count|
135
+ count.must_equal 1
136
+ EM.stop
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ it "should create non existing item (upsert)" do
143
+ EM.run do
144
+ @collection.safe_update({ artist: "Bjork" }, { "$set" => { country: "Iceland" } }, { upsert: true }) do |err, resp|
145
+ @collection.count(query: { artist: "Bjork" }) do |err, cnt|
146
+ cnt.must_equal 1
147
+ EM.stop
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ it "should update all matching data (multi_update)" do
154
+ EM.run do
155
+ @collection.safe_update({ artist: "Madonna" }, { "$set" => { country: "USA" } }, {multi_update: true}) do |err, resp|
156
+ @collection.find(artist: "Madonna").all do |err, docs|
157
+ docs.each{ |d| d["country"].must_equal "USA" }
158
+ EM.stop
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
164
+
165
+ # REMOVE
166
+
167
+ describe "remove" do
168
+ it "should delete all matching docs" do
169
+ EM.run do
170
+ @collection.safe_delete(artist: "Madonna") do
171
+ @collection.count(query: { artist: "Madonna" }) do |err, cnt|
172
+ cnt.must_equal 0
173
+ EM.stop
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ it "should delete first matching doc (single_remove)" do
180
+ EM.run do
181
+ @collection.safe_delete({ artist: "Madonna" }, single_remove: true) do
182
+ @collection.count(query: { artist: "Madonna" }) do |err, cnt|
183
+ cnt.must_equal 9
184
+ EM.stop
185
+ end
186
+ end
187
+ end
188
+ end
189
+ end
190
+
191
+ # COUNT
192
+
193
+ describe "count" do
194
+ it "should count all docs" do
195
+ EM.run do
196
+ @collection.count do |err, count|
197
+ count.must_equal 20
198
+ EM.stop
199
+ end
200
+ end
201
+ end
202
+
203
+ it "should count all docs with query" do
204
+ EM.run do
205
+ @collection.count(query: { artist: "Madonna" }) do |err, count|
206
+ count.must_equal 10
207
+ EM.stop
208
+ end
209
+ end
210
+ end
211
+
212
+ it "should count all docs with limit" do
213
+ EM.run do
214
+ @collection.count(query: { artist: "Madonna" }, limit: 5) do |err, count|
215
+ count.must_equal 5
216
+ EM.stop
217
+ end
218
+ end
219
+ end
220
+
221
+ it "should count all docs with limit and skip" do
222
+ EM.run do
223
+ @collection.count(query: { artist: "Madonna" }, limit: 5, skip: 6) do |err, count|
224
+ count.must_equal 4
225
+ EM.stop
226
+ end
227
+ end
228
+ end
229
+ end
230
+
231
+ # ENSURE/DROP INDEX
232
+
233
+ describe "ensure_index" do
234
+ before do
235
+ EM.run do
236
+ @collection.drop_indexes do |err, resp|
237
+ raise err if err
238
+ EM.stop
239
+ end
240
+ end
241
+ end
242
+
243
+ it "should create index" do
244
+ EM.run do
245
+ @collection.safe_ensure_index(title: 1) do
246
+ @collection.get_indexes do |err, docs|
247
+ docs.any?{ |doc| doc["key"] == {"title" => 1}}.must_equal true
248
+ EM.stop
249
+ end
250
+ end
251
+ end
252
+ end
253
+
254
+ it "should create sparse index" do
255
+ EM.run do
256
+ @collection.safe_ensure_index({ title: 1 }, sparse: true) do
257
+ @collection.get_indexes do |err, docs|
258
+ docs.any?{ |doc| doc["key"] == {"title" => 1} && doc["sparse"] == true }.must_equal true
259
+ EM.stop
260
+ end
261
+ end
262
+ end
263
+ end
264
+
265
+ it "should create unique index" do
266
+ EM.run do
267
+ @collection.safe_ensure_index({ some_field: 1 }, unique: true, sparse: true) do |err, resp|
268
+ @collection.get_indexes do |err, docs|
269
+ docs.any?{ |doc| doc["key"] == {"some_field" => 1} && doc["unique"] == true }.must_equal true
270
+ EM.stop
271
+ end
272
+ end
273
+ end
274
+ end
275
+
276
+ it "should drop single index" do
277
+ EM.run do
278
+ @collection.safe_ensure_index(title: 1) do
279
+ @collection.get_indexes do |err, docs|
280
+ docs.any?{ |doc| doc["key"] == {"title" => 1}}.must_equal true
281
+ @collection.drop_index(title: 1) do
282
+ @collection.get_indexes do |err, docs|
283
+ docs.any?{ |doc| doc["key"] == {"title" => 1}}.must_equal false
284
+ EM.stop
285
+ end
286
+ end
287
+ end
288
+ end
289
+ end
290
+ end
291
+
292
+ it "should drop all indexes (except primary on _id)" do
293
+ EM.run do
294
+ @collection.safe_ensure_index(title: 1) do
295
+ @collection.get_indexes do |err, docs|
296
+ docs.any?{ |doc| doc["key"] == {"title" => 1}}.must_equal true
297
+ @collection.drop_indexes do |err|
298
+ @collection.get_indexes do |err, docs|
299
+ docs.select{ |d| d["ns"] == "dbTest.testCollection" }.size.must_equal 1
300
+ EM.stop
301
+ end
302
+ end
303
+ end
304
+ end
305
+ end
306
+ end
307
+ end
308
+ end