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