active_record_shards 3.0.0.beta1 → 3.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,515 +0,0 @@
1
- require_relative 'helper'
2
-
3
- describe "connection switching" do
4
- i_suck_and_my_tests_are_order_dependent!
5
-
6
- describe "shard switching" do
7
- it "only switch connection on sharded models" do
8
- assert_using_database('ars_test', Ticket)
9
- assert_using_database('ars_test', Account)
10
-
11
- ActiveRecord::Base.on_shard(0) do
12
- assert_using_database('ars_test_shard0', Ticket)
13
- assert_using_database('ars_test', Account)
14
- end
15
- end
16
-
17
- it "switch to shard and back" do
18
- assert_using_database('ars_test')
19
- ActiveRecord::Base.on_slave { assert_using_database('ars_test_slave') }
20
-
21
- ActiveRecord::Base.on_shard(0) do
22
- assert_using_database('ars_test_shard0')
23
- ActiveRecord::Base.on_slave { assert_using_database('ars_test_shard0_slave') }
24
-
25
- ActiveRecord::Base.on_shard(nil) do
26
- assert_using_database('ars_test')
27
- ActiveRecord::Base.on_slave { assert_using_database('ars_test_slave') }
28
- end
29
-
30
- assert_using_database('ars_test_shard0')
31
- ActiveRecord::Base.on_slave { assert_using_database('ars_test_shard0_slave') }
32
- end
33
-
34
- assert_using_database('ars_test')
35
- ActiveRecord::Base.on_slave { assert_using_database('ars_test_slave') }
36
- end
37
-
38
- describe "on_first_shard" do
39
- it "use the first shard" do
40
- ActiveRecord::Base.on_first_shard {
41
- assert_using_database('ars_test_shard0')
42
- }
43
- end
44
- end
45
-
46
- describe "on_all_shards" do
47
- before do
48
- @shard_0_master = ActiveRecord::Base.on_shard(0) {ActiveRecord::Base.connection}
49
- @shard_1_master = ActiveRecord::Base.on_shard(1) {ActiveRecord::Base.connection}
50
- refute_equal(@shard_0_master.select_value("SELECT DATABASE()"), @shard_1_master.select_value("SELECT DATABASE()"))
51
- end
52
-
53
- it "execute the block on all shard masters" do
54
- result = ActiveRecord::Base.on_all_shards do |shard|
55
- [ActiveRecord::Base.connection.select_value("SELECT DATABASE()"), shard]
56
- end
57
- database_names = result.map(&:first)
58
- database_shards = result.map(&:last)
59
-
60
- assert_equal(2, database_names.size)
61
- assert_includes(database_names, @shard_0_master.select_value("SELECT DATABASE()"))
62
- assert_includes(database_names, @shard_1_master.select_value("SELECT DATABASE()"))
63
-
64
- assert_equal(2, database_shards.size)
65
- assert_includes(database_shards, "0")
66
- assert_includes(database_shards, "1")
67
- end
68
-
69
- it "execute the block unsharded" do
70
- ActiveRecord::Base.expects(:supports_sharding?).returns false
71
- result = ActiveRecord::Base.on_all_shards do |shard|
72
- [ActiveRecord::Base.connection.select_value("SELECT DATABASE()"), shard]
73
- end
74
- assert_equal [["ars_test", nil]], result
75
- end
76
- end
77
- end
78
-
79
- describe "default shard selection" do
80
- describe "of nil" do
81
- before do
82
- ActiveRecord::Base.default_shard = nil
83
- end
84
-
85
- it "use unsharded db for sharded models" do
86
- assert_using_database('ars_test', Ticket)
87
- assert_using_database('ars_test', Account)
88
- end
89
- end
90
-
91
- describe "value" do
92
- before do
93
- ActiveRecord::Base.default_shard = 0
94
- end
95
-
96
- after do
97
- ActiveRecord::Base.default_shard = nil
98
- end
99
-
100
- it "use default shard db for sharded models" do
101
- assert_using_database('ars_test_shard0', Ticket)
102
- assert_using_database('ars_test', Account)
103
- end
104
-
105
- it "still be able to switch to shard nil" do
106
- ActiveRecord::Base.on_shard(nil) do
107
- assert_using_database('ars_test', Ticket)
108
- assert_using_database('ars_test', Account)
109
- end
110
- end
111
- end
112
- end
113
-
114
- describe "ActiveRecord::Base.columns" do
115
- before do
116
- ActiveRecord::Base.default_shard = nil
117
- end
118
-
119
- describe "for unsharded models" do
120
- it "use the non-sharded connection" do
121
- assert_using_database('ars_test', Account)
122
- Account.connection.execute("alter table accounts add column foo int")
123
-
124
- assert Account.column_names.include?('foo')
125
- end
126
-
127
- after do
128
- ActiveRecord::Base.connection.execute("alter table accounts drop column foo")
129
- Account.reset_column_information
130
- end
131
- end
132
-
133
- describe "for sharded models" do
134
- before do
135
- ActiveRecord::Base.on_first_shard do
136
- ActiveRecord::Base.connection.execute("alter table tickets add column foo int")
137
- end
138
- end
139
-
140
- after do
141
- ActiveRecord::Base.on_first_shard do
142
- ActiveRecord::Base.connection.execute("alter table tickets drop column foo")
143
- Ticket.reset_column_information
144
- end
145
- end
146
-
147
- it "get colmns from the first shard" do
148
- assert Ticket.column_names.include?('foo')
149
- end
150
-
151
- it "have correct from_shard" do
152
- ActiveRecord::Base.on_all_shards do |shard|
153
- assert_equal shard, Ticket.new.from_shard
154
- end
155
- end
156
- end
157
- end
158
-
159
- describe "ActiveRecord::Base.table_exists?" do
160
- before do
161
- ActiveRecord::Base.default_shard = nil
162
- end
163
-
164
- describe "for unsharded models" do
165
- it "use the unsharded connection" do
166
- class UnshardedModel < ActiveRecord::Base
167
- not_sharded
168
- end
169
- UnshardedModel.connection.execute("create table unsharded_models (id int)")
170
- assert(UnshardedModel.table_exists?)
171
-
172
- ActiveRecord::Base.on_all_shards do
173
- assert !ActiveRecord::Base.connection.table_exists?("unsharded_models")
174
- end
175
- end
176
- end
177
-
178
- describe "for sharded models" do
179
- it "try the first shard" do
180
- class ShardedModel < ActiveRecord::Base
181
- end
182
-
183
- ActiveRecord::Base.on_first_shard do
184
- ShardedModel.connection.execute("create table sharded_models (id int)")
185
- end
186
-
187
- assert ShardedModel.table_exists?
188
- end
189
- end
190
- end
191
-
192
- describe "in an unsharded environment" do
193
- before do
194
- silence_warnings { ::RAILS_ENV = 'test2' }
195
- ActiveRecord::Base.establish_connection(::RAILS_ENV)
196
- assert_using_database('ars_test2', Ticket)
197
- end
198
-
199
- after do
200
- silence_warnings { ::RAILS_ENV = 'test' }
201
- ActiveRecord::Base.establish_connection(::RAILS_ENV)
202
- assert_using_database('ars_test', Ticket)
203
- end
204
-
205
- if ActiveRecord::VERSION::MAJOR >= 3
206
- it "be able to find by column" do
207
- Account.where(:name => "peter").to_sql # does not blow up
208
- end
209
-
210
- it "have correct engine" do
211
- assert_equal Account, Account.arel_engine
212
- end
213
- end
214
-
215
- describe "shard switching" do
216
- it "just stay on the main db" do
217
- assert_using_database('ars_test2', Ticket)
218
- assert_using_database('ars_test2', Account)
219
-
220
- ActiveRecord::Base.on_shard(0) do
221
- assert_using_database('ars_test2', Ticket)
222
- assert_using_database('ars_test2', Account)
223
- end
224
- end
225
- end
226
-
227
- describe "on_all_shards" do
228
- before do
229
- @database_names = []
230
- ActiveRecord::Base.on_all_shards do
231
- @database_names << ActiveRecord::Base.connection.select_value("SELECT DATABASE()")
232
- end
233
- end
234
-
235
- it "execute the block on all shard masters" do
236
- assert_equal([ActiveRecord::Base.connection.select_value("SELECT DATABASE()")], @database_names)
237
- end
238
- end
239
- end
240
-
241
- describe "slave driving" do
242
- describe "without slave configuration" do
243
-
244
- before do
245
- ActiveRecord::Base.configurations.delete('test_slave')
246
- if ActiveRecord::VERSION::MAJOR == 4
247
- ActiveRecord::Base.connection_handler.connection_pool_list.clear
248
- else
249
- ActiveRecord::Base.connection_handler.connection_pools.clear
250
- end
251
- ActiveRecord::Base.establish_connection('test')
252
- end
253
-
254
- it "default to the master database" do
255
- Account.create!
256
-
257
- ActiveRecord::Base.on_slave { assert_using_master_db }
258
- Account.on_slave { assert_using_master_db }
259
- Ticket.on_slave { assert_using_master_db }
260
- end
261
-
262
- it "successfully execute queries" do
263
- Account.create!
264
- assert_using_master_db
265
-
266
- assert_equal Account.count, ActiveRecord::Base.on_slave { Account.count }
267
- assert_equal Account.count, Account.on_slave { Account.count }
268
- end
269
-
270
- end
271
-
272
- describe "with slave configuration" do
273
-
274
- it "successfully execute queries" do
275
- assert_using_master_db
276
- Account.create!
277
-
278
- assert_equal(1, Account.count)
279
- assert_equal(0, ActiveRecord::Base.on_slave { Account.count })
280
- end
281
-
282
- it "support global on_slave blocks" do
283
- assert_using_master_db
284
- assert_using_master_db
285
-
286
- ActiveRecord::Base.on_slave do
287
- assert_using_slave_db
288
- assert_using_slave_db
289
- end
290
-
291
- assert_using_master_db
292
- assert_using_master_db
293
- end
294
-
295
- it "support conditional methods" do
296
- assert_using_master_db
297
-
298
- Account.on_slave_if(true) do
299
- assert_using_slave_db
300
- end
301
-
302
- assert_using_master_db
303
-
304
- Account.on_slave_if(false) do
305
- assert_using_master_db
306
- end
307
-
308
- Account.on_slave_unless(true) do
309
- assert_using_master_db
310
- end
311
-
312
- Account.on_slave_unless(false) do
313
- assert_using_slave_db
314
- end
315
- end
316
-
317
- describe "a model loaded with the slave" do
318
- before do
319
- Account.connection.execute("INSERT INTO accounts (id, name, created_at, updated_at) VALUES(1000, 'master_name', '2009-12-04 20:18:48', '2009-12-04 20:18:48')")
320
- assert(Account.find(1000))
321
- assert_equal('master_name', Account.find(1000).name)
322
-
323
- Account.on_slave.connection.execute("INSERT INTO accounts (id, name, created_at, updated_at) VALUES(1000, 'slave_name', '2009-12-04 20:18:48', '2009-12-04 20:18:48')")
324
-
325
- @model = Account.on_slave.find(1000)
326
- assert(@model)
327
- assert_equal('slave_name', @model.name)
328
- end
329
-
330
- it "read from master on reload" do
331
- @model.reload
332
- assert_equal('master_name', @model.name)
333
- end
334
-
335
- it "be marked as read only" do
336
- assert(@model.readonly?)
337
- end
338
-
339
- it "be marked as comming from the slave" do
340
- assert(@model.from_slave?)
341
- end
342
- end
343
-
344
- describe "a inherited model without cached columns hash" do
345
- # before columns -> with_scope -> type-condition -> columns == loop
346
- it "not loop when on slave by default" do
347
- Person.on_slave_by_default = true
348
- assert User.on_slave_by_default?
349
- assert User.finder_needs_type_condition?
350
-
351
- User.instance_variable_set(:@columns_hash, nil)
352
- User.columns_hash
353
- end
354
- end
355
-
356
- describe "a model loaded with the master" do
357
- before do
358
- Account.connection.execute("INSERT INTO accounts (id, name, created_at, updated_at) VALUES(1000, 'master_name', '2009-12-04 20:18:48', '2009-12-04 20:18:48')")
359
- @model = Account.first
360
- assert(@model)
361
- assert_equal('master_name', @model.name)
362
- end
363
-
364
- # TODO mocha raises stack level too deep on ActiveRecord 3.2+
365
- if ActiveRecord::VERSION::STRING < "3.2.0"
366
- it "not unnecessary call with_scope" do
367
- Account.expects(:with_scope).never
368
- Account.on_master.first
369
- end
370
- end
371
-
372
- it "not unset readonly" do
373
- @model = Account.on_master.scoped(:readonly => true).first
374
- assert(@model.readonly?)
375
- end
376
-
377
- it "not be marked as read only" do
378
- assert(!@model.readonly?)
379
- end
380
-
381
- it "not be marked as comming from the slave" do
382
- assert(!@model.from_slave?)
383
- end
384
- end
385
-
386
- # TODO: make all this stuff rails 3 compatible.
387
- describe "with finds routed to the slave by default" do
388
- before do
389
- Account.on_slave_by_default = true
390
- Account.connection.execute("INSERT INTO accounts (id, name, created_at, updated_at) VALUES(1000, 'master_name', '2009-12-04 20:18:48', '2009-12-04 20:18:48')")
391
- Account.on_slave.connection.execute("INSERT INTO accounts (id, name, created_at, updated_at) VALUES(1000, 'slave_name', '2009-12-04 20:18:48', '2009-12-04 20:18:48')")
392
- Account.on_slave.connection.execute("INSERT INTO accounts (id, name, created_at, updated_at) VALUES(1001, 'slave_name2', '2009-12-04 20:18:48', '2009-12-04 20:18:48')")
393
- end
394
-
395
- it "find() by default on the slave" do
396
- account = Account.find(1000)
397
- assert_equal 'slave_name', account.name
398
- end
399
-
400
- it "count() by default on the slave" do
401
- count = Account.all.size
402
- assert_equal 2, count
403
- end
404
-
405
- it "reload() on the master" do
406
- account = Account.find(1000)
407
- assert_equal 'master_name', account.reload.name
408
- end
409
-
410
- it "do exists? on the slave" do
411
- if Account.respond_to?(:exists?)
412
- assert Account.exists?(1001)
413
- end
414
- end
415
-
416
- it "does exists? on the slave with a named scope" do
417
- AccountThing.on_slave_by_default = true
418
- Account.on_slave.connection.execute("INSERT INTO account_things (id, account_id) VALUES(123125, 1000)")
419
- assert AccountThing.enabled.exists?(123125)
420
- Account.on_slave.connection.execute("DELETE FROM account_things")
421
- AccountThing.on_slave_by_default = false
422
- end
423
-
424
- it "count associations on the slave" do
425
- AccountThing.on_slave_by_default = true
426
- Account.on_slave.connection.execute("INSERT INTO account_things (id, account_id) VALUES(123123, 1000)")
427
- Account.on_slave.connection.execute("INSERT INTO account_things (id, account_id) VALUES(123124, 1000)")
428
- assert_equal 2, Account.find(1000).account_things.size
429
- AccountThing.on_slave_by_default = false
430
- end
431
-
432
- it "Allow override using on_master" do
433
- model = Account.on_master.find(1000)
434
- assert_equal "master_name", model.name
435
- end
436
-
437
- it "not override on_master with on_slave" do
438
- model = Account.on_master { Account.on_slave.find(1000) }
439
- assert_equal "master_name", model.name
440
- end
441
-
442
- it "override on_slave with on_master" do
443
- model = Account.on_slave { Account.on_master.find(1000) }
444
- assert_equal "master_name", model.name
445
- end
446
-
447
- it "propogate the default_slave setting to inherited classes" do
448
- assert AccountInherited.on_slave_by_default?
449
- end
450
-
451
- after do
452
- Account.on_slave_by_default = false
453
- end
454
- end
455
- end
456
-
457
- describe "slave proxy" do
458
- it "successfully execute queries" do
459
- assert_using_master_db
460
- Account.create!
461
-
462
- refute_equal Account.count, Account.on_slave.count
463
- end
464
-
465
- it "work on association collections" do
466
- begin
467
- assert_using_master_db
468
- account = Account.create!
469
-
470
- account.tickets.create! :title => 'master ticket'
471
-
472
- Ticket.on_slave {
473
- account.tickets.create! :title => 'slave ticket'
474
- }
475
-
476
- assert_equal "master ticket", account.tickets.first.title
477
- assert_equal "slave ticket", account.tickets.on_slave.first.title
478
- rescue Exception
479
- retried ||= 0
480
- retried += 1
481
- puts "Failed in #{__LINE__}##{retried}"
482
- retry if retried < 3
483
- end
484
- end
485
- end
486
- end
487
-
488
- describe "alternative connections" do
489
- it "not interfere with other connections" do
490
- assert_using_database('ars_test', Account)
491
- assert_using_database('ars_test', Ticket)
492
- assert_using_database('ars_test_alternative', Email)
493
-
494
- ActiveRecord::Base.on_shard(0) do
495
- assert_using_database('ars_test', Account)
496
- assert_using_database('ars_test_shard0', Ticket)
497
- assert_using_database('ars_test_alternative', Email)
498
- end
499
-
500
- assert_using_database('ars_test', Account)
501
- assert_using_database('ars_test', Ticket)
502
- assert_using_database('ars_test_alternative', Email)
503
- end
504
- end
505
-
506
- it "raises an exception if a connection is not found" do
507
- ActiveRecord::Base.on_shard(0) do
508
- ActiveRecord::Base.connection_handler.remove_connection(Ticket)
509
- assert_raises(ActiveRecord::ConnectionNotEstablished) do
510
- ActiveRecord::Base.connection_handler.retrieve_connection_pool(Ticket)
511
- assert_using_database('ars_test_shard0', Ticket)
512
- end
513
- end
514
- end
515
- end