active_record_handlersocket 0.0.1

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