active_record_handlersocket 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module ActiveRecordHandlersocket
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+
3
+ describe "ConnectionSpec" do
4
+ let :klass do
5
+ Person
6
+ end
7
+
8
+ let :another_klass do
9
+ Hobby
10
+ end
11
+
12
+ describe "hs_reconnect!" do
13
+ before :each do
14
+ ActiveRecord::Base.__send__(:hs_read_connection).close
15
+ ActiveRecord::Base.__send__(:hs_reset_opened_indexes)
16
+ end
17
+
18
+ it "should reconnect to handlersocket" do
19
+ expect(ActiveRecord::Base.hs_reconnect!).to be
20
+ expect{
21
+ klass.hsfind_by_id(1)
22
+ }.not_to raise_error(ActiveRecordHandlerSocket::CannotConnectError)
23
+ end
24
+
25
+ it "should reset opened indexes" do
26
+ expect(ActiveRecord::Base.hs_reconnect!).to be
27
+
28
+ expect(ActiveRecord::Base.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "id")][:opened]).not_to be
29
+ expect(ActiveRecord::Base.__send__(:hs_indexes)[another_klass.__send__(:hs_index_key, "id")][:opened]).not_to be
30
+ end
31
+ end
32
+
33
+ describe "hs_active?" do
34
+ context "when connected" do
35
+ before :each do
36
+ # open index
37
+ klass.hsfind_by_id(1)
38
+ end
39
+
40
+ it "should return true when connected" do
41
+ expect(ActiveRecord::Base.hs_active?).to be
42
+ end
43
+ end
44
+
45
+ context "when closed" do
46
+ before :each do
47
+ ActiveRecord::Base.__send__(:hs_read_connection).close
48
+ end
49
+
50
+ after :each do
51
+ ActiveRecord::Base.hs_reconnect!
52
+ end
53
+
54
+ it "should return false" do
55
+ expect(ActiveRecord::Base.hs_active?).not_to be
56
+ end
57
+ end
58
+ end
59
+
60
+ describe "hs_establish_connection" do
61
+ context "when no name given" do
62
+ before :each do
63
+ @original_connections = ActiveRecord::Base.__send__(:hs_connections)
64
+ ActiveRecordHandlerSocket::Connection::PrivateMethods.__send__(:class_variable_set, :@@hs_connections, {})
65
+ end
66
+
67
+ after :each do
68
+ ActiveRecordHandlerSocket::Connection::PrivateMethods.__send__(:class_variable_set, :@@hs_connections, @original_connections)
69
+ end
70
+
71
+ it "should add read connection" do
72
+ ActiveRecord::Base.__send__(:hs_establish_connection)
73
+ expect(ActiveRecord::Base.__send__(:hs_connections)[:read]).to be_kind_of(HandlerSocket)
74
+ end
75
+ end
76
+
77
+ context "when read connection" do
78
+ before :each do
79
+ @original_connections = ActiveRecord::Base.__send__(:hs_connections)
80
+ ActiveRecordHandlerSocket::Connection::PrivateMethods.__send__(:class_variable_set, :@@hs_connections, {})
81
+ end
82
+
83
+ after :each do
84
+ ActiveRecordHandlerSocket::Connection::PrivateMethods.__send__(:class_variable_set, :@@hs_connections, @original_connections)
85
+ end
86
+
87
+ it "should add read connection" do
88
+ ActiveRecord::Base.__send__(:hs_establish_connection, "test_hs_read")
89
+ expect(ActiveRecord::Base.__send__(:hs_connections)[:read]).to be_kind_of(HandlerSocket)
90
+ end
91
+ end
92
+
93
+ context "when unknown configuration name given" do
94
+ it "should raise error" do
95
+ expect{
96
+ ActiveRecord::Base.__send__(:hs_establish_connection, "production_hs_read")
97
+ }.to raise_error(ArgumentError)
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "hs_read_connection" do
103
+ it "should return handlersocket" do
104
+ expect(ActiveRecord::Base.__send__(:hs_read_connection)).to be_kind_of(HandlerSocket)
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,313 @@
1
+ require 'spec_helper'
2
+
3
+ describe "FinderSpec" do
4
+ let :klass do
5
+ Person
6
+ end
7
+
8
+ let :another_klass do
9
+ Hobby
10
+ end
11
+
12
+ before :each do
13
+ @bob = FactoryGirl.create(:bob)
14
+ FactoryGirl.create(:pharrell)
15
+ end
16
+
17
+ describe "hsfind" do
18
+ context "when defined by handlersocket" do
19
+ before :each do
20
+ klass.delete_all
21
+ end
22
+
23
+ context "for :first" do
24
+ it "should call hsfind with method_missing" do
25
+ expect(klass).not_to respond_to(:hsfind_by_id)
26
+ expect(klass.hsfind_by_id(1)).to be_nil
27
+ end
28
+ end
29
+
30
+ context "for :multi" do
31
+ it "should call hsfind with method_missing" do
32
+ expect(klass).not_to respond_to(:hsfind_multi_by_id)
33
+ expect(klass.hsfind_multi_by_id(1)).to be_empty
34
+ end
35
+ end
36
+ end
37
+
38
+ context "when before definition by handlersocket" do
39
+ context "for :first" do
40
+ it "should raise error" do
41
+ expect{
42
+ klass.hsfind_by_name("Bob")
43
+ }.to raise_error(ActiveRecordHandlerSocket::UnknownIndexError)
44
+ end
45
+ end
46
+
47
+ context "for :multi" do
48
+ it "should raise error" do
49
+ expect{
50
+ klass.hsfind_multi_by_name("Bob")
51
+ }.to raise_error(ActiveRecordHandlerSocket::UnknownIndexError)
52
+ end
53
+ end
54
+ end
55
+
56
+ context "when records exist" do
57
+ context "for :first" do
58
+ it "should get one record by id" do
59
+ person = klass.find_by_id(1)
60
+ hs_person = klass.hsfind_by_id(1)
61
+
62
+ expect(hs_person).to eql(person)
63
+ end
64
+
65
+ it "should get nil by unknown id" do
66
+ person = klass.find_by_id(9)
67
+ hs_person = klass.hsfind_by_id(9)
68
+
69
+ expect(person).to be_nil
70
+ expect(hs_person).to be_nil
71
+ end
72
+ end
73
+
74
+ context "for :multi" do
75
+ it "should get one record by id" do
76
+ person = klass.find_all_by_id([1])
77
+ hs_person = klass.hsfind_multi_by_id(1)
78
+
79
+ expect(hs_person).to eql(person)
80
+ end
81
+
82
+ it "should get some records by ids" do
83
+ people = klass.find_all_by_id([1, 2])
84
+ hs_people = klass.hsfind_multi_by_id(1, 2)
85
+
86
+ expect(hs_people).to eql(people)
87
+ end
88
+
89
+ it "should get empty array by unknown id" do
90
+ people = klass.find_all_by_id([9])
91
+ hs_people = klass.hsfind_multi_by_id(9)
92
+
93
+ expect(people).to be_empty
94
+ expect(hs_people).to be_empty
95
+ end
96
+ end
97
+ end
98
+
99
+ context "when finder with options" do
100
+ context "for :single" do
101
+ context "with operator option" do
102
+ it "should find greater value record" do
103
+ hs_person = klass.hsfind_by_id(0, :operator => ">")
104
+
105
+ expect(hs_person).to be_kind_of(klass)
106
+
107
+ hs_person = klass.hsfind_by_id(3, :operator => ">")
108
+
109
+ expect(hs_person).to be_nil
110
+ end
111
+
112
+ it "should find less value record" do
113
+ person = klass.find_by_id(2)
114
+ hs_person = klass.hsfind_by_id(3, :operator => "<")
115
+
116
+ expect(hs_person).to eql(person)
117
+
118
+ hs_person = klass.hsfind_by_id(0, :operator => "<")
119
+
120
+ expect(hs_person).to be_nil
121
+ end
122
+ end
123
+
124
+ context "with limit option" do
125
+ it "should ignore limit option" do
126
+ person = klass.find_by_id(2)
127
+ hs_person = klass.hsfind_by_id(3, :operator => "<", :limit => 10)
128
+
129
+ expect(hs_person).to eql(person)
130
+ expect(hs_person).not_to be_kind_of(Array)
131
+ end
132
+ end
133
+ end
134
+
135
+ context "for :multi" do
136
+ context "with operator option" do
137
+ it "should find greater value record" do
138
+ hs_people = klass.hsfind_multi_by_id(0, :operator => ">")
139
+
140
+ expect(hs_people.size).to eql(1)
141
+ expect(hs_people.first).to be_kind_of(klass)
142
+
143
+ hs_people = klass.hsfind_multi_by_id(3, :operator => ">")
144
+
145
+ expect(hs_people).to be_empty
146
+ end
147
+
148
+ it "should find less value record" do
149
+ people = klass.find_all_by_id([2])
150
+ hs_people = klass.hsfind_multi_by_id(3, :operator => "<")
151
+
152
+ expect(hs_people).to eql(people)
153
+
154
+ hs_people = klass.hsfind_multi_by_id(0, :operator => "<")
155
+
156
+ expect(hs_people).to be_empty
157
+ end
158
+ end
159
+
160
+ context "with limit option" do
161
+ it "should find greater value records" do
162
+ people = klass.find_all_by_id([1, 2])
163
+ hs_people = klass.hsfind_multi_by_id(0, :operator => ">", :limit => 10)
164
+
165
+ expect(hs_people).to eql(people)
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ describe "hsfind with connection" do
172
+ before :each do
173
+ ActiveRecord::Base.__send__(:hs_reconnect!)
174
+ end
175
+
176
+ it "should open index before find" do
177
+ expect{
178
+ klass.hsfind_by_id(1)
179
+ }.not_to raise_error(ActiveRecordHandlerSocket::CannotConnectError)
180
+ expect(ActiveRecord::Base.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "id")][:opened]).to be
181
+ end
182
+ end
183
+ end
184
+
185
+ describe "hs_open_index (before hsfind)" do
186
+ context "when index opened" do
187
+ it "should just return" do
188
+ expect(klass.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "id")][:opened]).to be
189
+
190
+ expect(klass.__send__(:hs_open_index, klass.__send__(:hs_index_key, "id"))).to be_nil
191
+ end
192
+ end
193
+
194
+ context "when open index" do
195
+ before :each do
196
+ ActiveRecord::Base.__send__(:hs_reconnect!)
197
+ end
198
+
199
+ it "should return true and mark opened" do
200
+ expect(klass.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "id")][:opened]).not_to be
201
+
202
+ expect(klass.__send__(:hs_open_index, klass.__send__(:hs_index_key, "id"))).to be
203
+
204
+ expect(klass.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "id")][:opened]).to be
205
+ end
206
+ end
207
+
208
+ context "when invalid result" do
209
+ before :each do
210
+ ActiveRecord::Base.__send__(:hs_reconnect!)
211
+ Hobby.hsfind_by_id(1)
212
+
213
+ ActiveRecord::Base.__send__(:hs_read_connection).stub(:open_index).and_return(2)
214
+ ActiveRecord::Base.__send__(:hs_read_connection).stub(:error).and_return("err")
215
+ end
216
+
217
+ it "should raise error" do
218
+ expect(klass.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "id")][:opened]).not_to be
219
+ expect(another_klass.__send__(:hs_indexes)[another_klass.__send__(:hs_index_key, "id")][:opened]).to be
220
+
221
+ expect{
222
+ klass.__send__(:hs_open_index, klass.__send__(:hs_index_key, "id"))
223
+ }.to raise_error(ArgumentError)
224
+
225
+ expect(klass.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "id")][:opened]).not_to be
226
+ expect(another_klass.__send__(:hs_indexes)[another_klass.__send__(:hs_index_key, "id")][:opened]).to be
227
+ end
228
+ end
229
+
230
+ context "when connection error" do
231
+ before :each do
232
+ ActiveRecord::Base.__send__(:hs_reconnect!)
233
+ another_klass.hsfind_by_id(1)
234
+
235
+ ActiveRecord::Base.__send__(:hs_read_connection).stub(:open_index).and_return(-1)
236
+ ActiveRecord::Base.__send__(:hs_read_connection).stub(:error).and_return("connection lost")
237
+ end
238
+
239
+ it "should raise error" do
240
+ expect(klass.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "id")][:opened]).not_to be
241
+ expect(another_klass.__send__(:hs_indexes)[another_klass.__send__(:hs_index_key, "id")][:opened]).to be
242
+
243
+ expect{
244
+ klass.__send__(:hs_open_index, klass.__send__(:hs_index_key, "id"))
245
+ }.to raise_error(ActiveRecordHandlerSocket::CannotConnectError)
246
+
247
+ expect(klass.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "id")][:opened]).not_to be
248
+ expect(another_klass.__send__(:hs_indexes)[another_klass.__send__(:hs_index_key, "id")][:opened]).not_to be
249
+ end
250
+ end
251
+ end
252
+
253
+ describe "hs_instantiate (after hsfind)" do
254
+ context "when valid result" do
255
+ it "should return single record" do
256
+ result = klass.__send__(:hs_instantiate, klass.__send__(:hs_index_key, "id"), [0, [["1", "MySQL", "19", "1"]]])
257
+
258
+ expect(result.size).to eql(1)
259
+
260
+ record = result.first
261
+ expect(record.id).to eql(1)
262
+ expect(record.name).to eql("MySQL")
263
+ expect(record.age).to eql(19)
264
+ expect(record.status).to be
265
+ end
266
+
267
+ it "should return multi record" do
268
+ result = klass.__send__(:hs_instantiate, klass.__send__(:hs_index_key, "id"), [0, [["1", "MySQL", "19", "1"], ["2", "%#123", "55", "0"]]])
269
+
270
+ expect(result.size).to eql(2)
271
+
272
+ record = result.first
273
+ expect(record.id).to eql(1)
274
+ expect(record.name).to eql("MySQL")
275
+ expect(record.age).to eql(19)
276
+ expect(record.status).to be
277
+
278
+ record = result.last
279
+ expect(record.id).to eql(2)
280
+ expect(record.name).to eql("%#123")
281
+ expect(record.age).to eql(55)
282
+ expect(record.status).not_to be
283
+ end
284
+ end
285
+
286
+ context "when invalid result" do
287
+ it "should raise error" do
288
+ expect{
289
+ klass.__send__(:hs_instantiate, klass.__send__(:hs_index_key, "id"), [2, "kpnum"])
290
+ }.to raise_error(ArgumentError)
291
+ end
292
+ end
293
+
294
+ context "when connection error" do
295
+ before :each do
296
+ klass.hsfind_by_id(1)
297
+ another_klass.hsfind_by_id(1)
298
+ end
299
+
300
+ it "should raise error and mark opened_index closed" do
301
+ expect(klass.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "id")][:opened]).to be
302
+ expect(another_klass.__send__(:hs_indexes)[another_klass.__send__(:hs_index_key, "id")][:opened]).to be
303
+
304
+ expect{
305
+ klass.__send__(:hs_instantiate, klass.__send__(:hs_index_key, "id"), [-1, "connection lost"])
306
+ }.to raise_error(ActiveRecordHandlerSocket::CannotConnectError)
307
+
308
+ expect(klass.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "id")][:opened]).not_to be
309
+ expect(another_klass.__send__(:hs_indexes)[another_klass.__send__(:hs_index_key, "id")][:opened]).not_to be
310
+ end
311
+ end
312
+ end
313
+ end
@@ -0,0 +1,149 @@
1
+ require 'spec_helper'
2
+
3
+ describe "ManagerSpec" do
4
+ let :klass do
5
+ Person
6
+ end
7
+
8
+ let :another_klass do
9
+ Hobby
10
+ end
11
+
12
+ before :each do
13
+ @bob = FactoryGirl.create(:bob)
14
+ FactoryGirl.create(:pharrell)
15
+
16
+ ActiveRecord::Base.__send__(:hs_reset_opened_indexes)
17
+ end
18
+
19
+ describe "module attributes" do
20
+ describe "hs_indexes" do
21
+ it "should be private" do
22
+ expect{
23
+ klass.hs_indexes
24
+ }.to raise_error(NoMethodError)
25
+ end
26
+
27
+ it "should not writable" do
28
+ expect{
29
+ klass.__send__(:hs_indexes=, {})
30
+ }.to raise_error(NoMethodError)
31
+ end
32
+ end
33
+
34
+ describe "hs_index_count_cache" do
35
+ it "should be private" do
36
+ expect{
37
+ klass.hs_index_count_cache
38
+ }.to raise_error(NoMethodError)
39
+ end
40
+
41
+ it "should not writable" do
42
+ expect{
43
+ klass.__send__(:hs_index_count_cache=, 0)
44
+ }.to raise_error(NoMethodError)
45
+ end
46
+ end
47
+ end
48
+
49
+ describe "handlersocket" do
50
+ it "should not overwrite by another class" do
51
+ expect(ActiveRecord::Base.__send__(:hs_indexes).has_key?(klass.__send__(:hs_index_key, "id"))).to be
52
+ expect(ActiveRecord::Base.__send__(:hs_indexes).has_key?(another_klass.__send__(:hs_index_key, "id"))).to be
53
+ end
54
+
55
+ it "should not increment id by each set" do
56
+ initial_count = klass.__send__(:hs_index_count_cache)
57
+ klass.__send__(:handlersocket, "test_id", "PRIMARY", ["id"])
58
+ expect(ActiveRecord::Base.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "test_id")][:id]).to eql(initial_count + 1)
59
+ another_klass.__send__(:handlersocket, "test_id", "PRIMARY", ["id"])
60
+ expect(ActiveRecord::Base.__send__(:hs_indexes)[another_klass.__send__(:hs_index_key, "test_id")][:id]).to eql(initial_count + 2)
61
+ klass.__send__(:handlersocket, "test_id", "PRIMARY", ["id"])
62
+ expect(ActiveRecord::Base.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "test_id")][:id]).to eql(initial_count + 3)
63
+ end
64
+ end
65
+
66
+ describe "hs_index_key" do
67
+ it "should be private method" do
68
+ expect{
69
+ klass.hs_index_key("bar")
70
+ }.to raise_error(NoMethodError)
71
+ end
72
+
73
+ it "should concat class name and key name" do
74
+ expect(klass.__send__(:hs_index_key, "bar")).to eql(klass.__send__(:hs_index_key, "bar"))
75
+ expect(another_klass.__send__(:hs_index_key, "baz")).to eql(another_klass.__send__(:hs_index_key, "baz"))
76
+ end
77
+ end
78
+
79
+ describe "hs_fetch_key" do
80
+ it "should be private method" do
81
+ expect{
82
+ klass.hs_fetch_key("id")
83
+ }.to raise_error(NoMethodError)
84
+ end
85
+
86
+ it "should fetch setting" do
87
+ setting = klass.__send__(:hs_fetch_key, klass.__send__(:hs_index_key, "id"))
88
+ expect(setting[:id]).to be_kind_of(Fixnum)
89
+ expect(setting[:index]).to eql("PRIMARY")
90
+ expect(setting[:fields]).to eql(["id", "name", "age", "status"])
91
+ expect(setting[:opened]).not_to be
92
+ end
93
+
94
+ it "should require index_key not just a key" do
95
+ expect{
96
+ klass.__send__(:hs_fetch_key, "id")
97
+ }.to raise_error(ActiveRecordHandlerSocket::UnknownIndexError)
98
+ end
99
+
100
+ it "should raise error with unknown key given" do
101
+ expect{
102
+ klass.__send__(:hs_fetch_key, klass.__send__(:hs_index_key, "name"))
103
+ }.to raise_error(ActiveRecordHandlerSocket::UnknownIndexError)
104
+ end
105
+
106
+ it "should include unknown key in error message" do
107
+ message = ""
108
+
109
+ begin
110
+ klass.__send__(:hs_fetch_key, klass.__send__(:hs_index_key, "name"))
111
+ rescue ActiveRecordHandlerSocket::UnknownIndexError => e
112
+ message = e.message
113
+ end
114
+
115
+ expect(message).to include(klass.__send__(:hs_index_key, "name"))
116
+ end
117
+ end
118
+
119
+ describe "hs_index_count" do
120
+ it "should be private method" do
121
+ expect{
122
+ klass.hs_index_count
123
+ }.to raise_error(NoMethodError)
124
+ end
125
+
126
+ it "should increment hs_index_count_cache" do
127
+ initial_count = klass.__send__(:hs_index_count_cache)
128
+ klass.__send__(:hs_index_count)
129
+ expect(klass.__send__(:hs_index_count_cache)).to eql(initial_count + 1)
130
+ klass.__send__(:hs_index_count)
131
+ expect(klass.__send__(:hs_index_count_cache)).to eql(initial_count + 2)
132
+ end
133
+ end
134
+
135
+ describe "hs_reset_opened_index" do
136
+ it "should mark not opened for all index settings" do
137
+ klass.hsfind_by_id(1)
138
+ another_klass.hsfind_by_id(1)
139
+
140
+ expect(ActiveRecord::Base.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "id")][:opened]).to be
141
+ expect(ActiveRecord::Base.__send__(:hs_indexes)[another_klass.__send__(:hs_index_key, "id")][:opened]).to be
142
+
143
+ klass.__send__(:hs_reset_opened_indexes)
144
+
145
+ expect(ActiveRecord::Base.__send__(:hs_indexes)[klass.__send__(:hs_index_key, "id")][:opened]).not_to be
146
+ expect(ActiveRecord::Base.__send__(:hs_indexes)[another_klass.__send__(:hs_index_key, "id")][:opened]).not_to be
147
+ end
148
+ end
149
+ end