active_record_shards 2.5.3 → 2.5.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/active_record_shards/finder_overrides.rb +56 -7
- data/test/configuration_parser_test.rb +10 -5
- data/test/connection_switching_test.rb +32 -29
- data/test/test.log +87286 -9815
- metadata +37 -9
@@ -1,25 +1,74 @@
|
|
1
1
|
module ActiveRecordShards
|
2
2
|
module FinderOverrides
|
3
|
-
|
3
|
+
CLASS_SLAVE_METHODS = [ :find_by_sql, :count_by_sql, :calculate, :find_one, :find_some, :find_every, :quote_value, :columns, :sanitize_sql_hash_for_conditions ]
|
4
|
+
|
4
5
|
def self.extended(base)
|
5
|
-
|
6
|
+
CLASS_SLAVE_METHODS.each do |slave_method|
|
6
7
|
base.class_eval <<-EOF, __FILE__, __LINE__ + 1
|
7
8
|
class <<self
|
8
|
-
def #{slave_method}
|
9
|
+
def #{slave_method}_with_default_slave(*args, &block)
|
9
10
|
on_slave_unless_tx do
|
10
|
-
#{slave_method}
|
11
|
+
#{slave_method}_without_default_slave(*args, &block)
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
14
|
-
alias_method_chain :#{slave_method}, :
|
15
|
+
alias_method_chain :#{slave_method}, :default_slave if respond_to?(:#{slave_method})
|
15
16
|
end
|
16
17
|
EOF
|
17
18
|
end
|
19
|
+
|
20
|
+
base.class_eval do
|
21
|
+
# fix ActiveRecord to do the right thing, and use our aliased quote_value
|
22
|
+
def quote_value(*args, &block)
|
23
|
+
self.class.quote_value(*args, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def transaction_with_slave_off(*args, &block)
|
28
|
+
if on_slave_by_default?
|
29
|
+
old_val = Thread.current[:_active_record_shards_slave_off]
|
30
|
+
Thread.current[:_active_record_shards_slave_off] = true
|
31
|
+
end
|
32
|
+
|
33
|
+
transaction_without_slave_off(*args, &block)
|
34
|
+
ensure
|
35
|
+
if on_slave_by_default?
|
36
|
+
Thread.current[:_active_record_shards_slave_off] = old_val
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
alias_method_chain :transaction, :slave_off
|
41
|
+
|
42
|
+
|
43
|
+
def table_exists_with_default_slave?(*args)
|
44
|
+
on_slave_unless_tx(*args) { table_exists_without_default_slave?(*args) }
|
45
|
+
end
|
46
|
+
|
47
|
+
alias_method_chain :table_exists?, :default_slave
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
ActiveRecord::Associations::HasAndBelongsToManyAssociation.class_eval do
|
53
|
+
def construct_sql_with_default_slave(*args, &block)
|
54
|
+
on_slave_unless_tx do
|
55
|
+
construct_sql_without_default_slave(*args, &block)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def construct_find_options_with_default_slave!(*args, &block)
|
60
|
+
on_slave_unless_tx do
|
61
|
+
construct_find_options_without_default_slave!(*args, &block)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
alias_method_chain :construct_sql, :default_slave if respond_to?(:construct_sql)
|
66
|
+
alias_method_chain :construct_find_options!, :default_slave if respond_to?(:construct_find_options!)
|
67
|
+
end
|
18
68
|
end
|
19
69
|
|
20
|
-
private
|
21
70
|
def on_slave_unless_tx(&block)
|
22
|
-
if on_slave_by_default? &&
|
71
|
+
if on_slave_by_default? && !Thread.current[:_active_record_shards_slave_off]
|
23
72
|
on_slave { yield }
|
24
73
|
else
|
25
74
|
yield
|
@@ -9,6 +9,7 @@ class ConfigurationParserTest < ActiveSupport::TestCase
|
|
9
9
|
context "main slave" do
|
10
10
|
setup { @conf = @exploded_conf['test_slave'] }
|
11
11
|
should "be exploded" do
|
12
|
+
@conf["shard_names"] = @conf["shard_names"].to_set
|
12
13
|
assert_equal({
|
13
14
|
"adapter" => "mysql",
|
14
15
|
"encoding" => "utf8",
|
@@ -17,7 +18,7 @@ class ConfigurationParserTest < ActiveSupport::TestCase
|
|
17
18
|
"username" => "root",
|
18
19
|
"password" => nil,
|
19
20
|
"host" => "main_slave_host",
|
20
|
-
"shard_names" => ["a", "b"]
|
21
|
+
"shard_names" => ["a", "b"].to_set
|
21
22
|
}, @conf)
|
22
23
|
end
|
23
24
|
end
|
@@ -26,6 +27,7 @@ class ConfigurationParserTest < ActiveSupport::TestCase
|
|
26
27
|
context "master" do
|
27
28
|
setup { @conf = @exploded_conf['test_shard_a'] }
|
28
29
|
should "be exploded" do
|
30
|
+
@conf["shard_names"] = @conf["shard_names"].to_set
|
29
31
|
assert_equal({
|
30
32
|
"adapter" => "mysql",
|
31
33
|
"encoding" => "utf8",
|
@@ -34,7 +36,7 @@ class ConfigurationParserTest < ActiveSupport::TestCase
|
|
34
36
|
"username" => "root",
|
35
37
|
"password" => nil,
|
36
38
|
"host" => "shard_a_host",
|
37
|
-
"shard_names" => ["a", "b"]
|
39
|
+
"shard_names" => ["a", "b"].to_set
|
38
40
|
}, @conf)
|
39
41
|
end
|
40
42
|
end
|
@@ -42,6 +44,7 @@ class ConfigurationParserTest < ActiveSupport::TestCase
|
|
42
44
|
context "slave" do
|
43
45
|
setup { @conf = @exploded_conf['test_shard_a_slave'] }
|
44
46
|
should "be exploded" do
|
47
|
+
@conf["shard_names"] = @conf["shard_names"].to_set
|
45
48
|
assert_equal({
|
46
49
|
"adapter" => "mysql",
|
47
50
|
"encoding" => "utf8",
|
@@ -50,7 +53,7 @@ class ConfigurationParserTest < ActiveSupport::TestCase
|
|
50
53
|
"username" => "root",
|
51
54
|
"password" => nil,
|
52
55
|
"host" => "shard_a_slave_host",
|
53
|
-
"shard_names" => ["a", "b"]
|
56
|
+
"shard_names" => ["a", "b"].to_set
|
54
57
|
}, @conf)
|
55
58
|
end
|
56
59
|
end
|
@@ -60,6 +63,7 @@ class ConfigurationParserTest < ActiveSupport::TestCase
|
|
60
63
|
context "master" do
|
61
64
|
setup { @conf = @exploded_conf['test_shard_b'] }
|
62
65
|
should "be exploded" do
|
66
|
+
@conf["shard_names"] = @conf["shard_names"].to_set
|
63
67
|
assert_equal({
|
64
68
|
"adapter" => "mysql",
|
65
69
|
"encoding" => "utf8",
|
@@ -68,7 +72,7 @@ class ConfigurationParserTest < ActiveSupport::TestCase
|
|
68
72
|
"username" => "root",
|
69
73
|
"password" => nil,
|
70
74
|
"host" => "shard_b_host",
|
71
|
-
"shard_names" => ["a", "b"]
|
75
|
+
"shard_names" => ["a", "b"].to_set
|
72
76
|
}, @conf)
|
73
77
|
end
|
74
78
|
end
|
@@ -76,6 +80,7 @@ class ConfigurationParserTest < ActiveSupport::TestCase
|
|
76
80
|
context "slave" do
|
77
81
|
setup { @conf = @exploded_conf['test_shard_b_slave'] }
|
78
82
|
should "be exploded" do
|
83
|
+
@conf["shard_names"] = @conf["shard_names"].to_set
|
79
84
|
assert_equal({
|
80
85
|
"adapter" => "mysql",
|
81
86
|
"encoding" => "utf8",
|
@@ -84,7 +89,7 @@ class ConfigurationParserTest < ActiveSupport::TestCase
|
|
84
89
|
"username" => "root",
|
85
90
|
"password" => nil,
|
86
91
|
"host" => "shard_b_host",
|
87
|
-
"shard_names" => ["a", "b"]
|
92
|
+
"shard_names" => ["a", "b"].to_set
|
88
93
|
}, @conf)
|
89
94
|
end
|
90
95
|
end
|
@@ -352,41 +352,44 @@ class ConnectionSwitchenTest < ActiveSupport::TestCase
|
|
352
352
|
end
|
353
353
|
end
|
354
354
|
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
355
|
+
# TODO: make all this stuff rails 3 compatible.
|
356
|
+
if Gem.loaded_specs['activerecord'].version < Gem::Version.create('3.0')
|
357
|
+
context "with finds routed to the slave by default" do
|
358
|
+
setup do
|
359
|
+
Account.on_slave_by_default = true
|
360
|
+
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')")
|
361
|
+
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')")
|
362
|
+
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')")
|
363
|
+
end
|
362
364
|
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
365
|
+
should "find() by default on the slave" do
|
366
|
+
account = Account.find(1000)
|
367
|
+
assert_equal 'slave_name', account.name
|
368
|
+
end
|
367
369
|
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
370
|
+
should "count() by default on the slave" do
|
371
|
+
count = Account.all.size
|
372
|
+
assert_equal 2, count
|
373
|
+
end
|
372
374
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
375
|
+
should "Allow override using on_master" do
|
376
|
+
model = Account.on_master.find(1000)
|
377
|
+
assert_equal "master_name", model.name
|
378
|
+
end
|
377
379
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
380
|
+
should "not override on_master with on_slave" do
|
381
|
+
model = Account.on_master { Account.on_slave.find(1000) }
|
382
|
+
assert_equal "master_name", model.name
|
383
|
+
end
|
382
384
|
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
385
|
+
should "override on_slave with on_master" do
|
386
|
+
model = Account.on_slave { Account.on_master.find(1000) }
|
387
|
+
assert_equal "master_name", model.name
|
388
|
+
end
|
387
389
|
|
388
|
-
|
389
|
-
|
390
|
+
teardown do
|
391
|
+
Account.on_slave_by_default = false
|
392
|
+
end
|
390
393
|
end
|
391
394
|
end
|
392
395
|
end
|