active_record_shards 2.6.6 → 2.6.7
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/active_record_shards/connection_pool.rb +3 -3
- data/lib/active_record_shards/connection_switcher.rb +6 -5
- data/lib/active_record_shards/default_slave_patches.rb +17 -4
- data/lib/active_record_shards/tasks.rb +7 -14
- data/test/connection_switching_test.rb +32 -12
- data/test/models.rb +8 -0
- data/test/schema.rb +7 -0
- metadata +4 -4
@@ -40,15 +40,15 @@ ActiveRecord::Base.singleton_class.class_eval do
|
|
40
40
|
alias_method_chain :establish_connection, :connection_pool_name
|
41
41
|
end
|
42
42
|
|
43
|
-
#
|
43
|
+
# old_code.sub('name', 'connection_pool_name')
|
44
44
|
if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0
|
45
45
|
class ActiveRecord::Base
|
46
46
|
def self.arel_engine
|
47
47
|
@arel_engine ||= begin
|
48
48
|
if self == ActiveRecord::Base
|
49
|
-
|
49
|
+
Arel::Table.engine
|
50
50
|
else
|
51
|
-
connection_handler.
|
51
|
+
connection_handler.connection_pools[connection_pool_name] ? self : superclass.arel_engine
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -26,12 +26,12 @@ module ActiveRecordShards
|
|
26
26
|
def on_all_shards(&block)
|
27
27
|
old_options = current_shard_selection.options
|
28
28
|
if supports_sharding?
|
29
|
-
shard_names.
|
29
|
+
shard_names.map do |shard|
|
30
30
|
switch_connection(:shard => shard)
|
31
31
|
yield(shard)
|
32
32
|
end
|
33
33
|
else
|
34
|
-
yield
|
34
|
+
[yield]
|
35
35
|
end
|
36
36
|
ensure
|
37
37
|
switch_connection(old_options)
|
@@ -83,15 +83,16 @@ module ActiveRecordShards
|
|
83
83
|
alias_method :with_slave_if, :on_slave_if
|
84
84
|
alias_method :with_slave_unless, :on_slave_unless
|
85
85
|
|
86
|
-
def on_cx_switch_block(which, &block)
|
86
|
+
def on_cx_switch_block(which, options = {}, &block)
|
87
87
|
old_options = current_shard_selection.options
|
88
88
|
switch_to_slave = (which == :slave && (@disallow_slave.nil? || @disallow_slave == 0))
|
89
89
|
switch_connection(:slave => switch_to_slave)
|
90
90
|
|
91
91
|
@disallow_slave = (@disallow_slave || 0) + 1 if which == :master
|
92
92
|
|
93
|
-
#
|
94
|
-
|
93
|
+
# we avoid_readonly_scope to prevent some stack overflow problems, like when
|
94
|
+
# .columns calls .with_scope which calls .columns and onward, endlessly.
|
95
|
+
if self == ActiveRecord::Base || !switch_to_slave || options[:construct_ro_scope] == false
|
95
96
|
yield
|
96
97
|
else
|
97
98
|
with_scope({:find => {:readonly => true}}, &block)
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module ActiveRecordShards
|
2
2
|
module DefaultSlavePatches
|
3
|
-
CLASS_SLAVE_METHODS = [ :find_by_sql, :count_by_sql, :calculate, :find_one, :find_some, :find_every, :quote_value, :
|
3
|
+
CLASS_SLAVE_METHODS = [ :find_by_sql, :count_by_sql, :calculate, :find_one, :find_some, :find_every, :quote_value, :sanitize_sql_hash_for_conditions ]
|
4
4
|
|
5
5
|
def self.extended(base)
|
6
6
|
base_methods = (base.methods | base.private_methods).map(&:to_sym)
|
7
7
|
(CLASS_SLAVE_METHODS & base_methods).each do |slave_method|
|
8
|
-
base.class_eval <<-
|
9
|
-
class <<self
|
8
|
+
base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
9
|
+
class << self
|
10
10
|
def #{slave_method}_with_default_slave(*args, &block)
|
11
11
|
on_slave_unless_tx do
|
12
12
|
#{slave_method}_without_default_slave(*args, &block)
|
@@ -15,7 +15,7 @@ module ActiveRecordShards
|
|
15
15
|
|
16
16
|
alias_method_chain :#{slave_method}, :default_slave
|
17
17
|
end
|
18
|
-
|
18
|
+
RUBY
|
19
19
|
end
|
20
20
|
|
21
21
|
base.class_eval do
|
@@ -29,6 +29,19 @@ module ActiveRecordShards
|
|
29
29
|
end
|
30
30
|
alias_method_chain :reload, :slave_off
|
31
31
|
|
32
|
+
class << self
|
33
|
+
def columns_with_default_slave(*args, &block)
|
34
|
+
if on_slave_by_default? && !Thread.current[:_active_record_shards_slave_off]
|
35
|
+
read_columns_from = :slave
|
36
|
+
else
|
37
|
+
read_columns_form = :master
|
38
|
+
end
|
39
|
+
|
40
|
+
on_cx_switch_block(read_columns_from, :construct_ro_scope => false) { columns_without_default_slave(*args, &block) }
|
41
|
+
end
|
42
|
+
alias_method_chain :columns, :default_slave
|
43
|
+
end
|
44
|
+
|
32
45
|
class << self
|
33
46
|
def transaction_with_slave_off(*args, &block)
|
34
47
|
if on_slave_by_default?
|
@@ -1,27 +1,20 @@
|
|
1
1
|
require 'active_record_shards'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
@tasks.delete(task_name.to_s)
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
def remove_task(task_name)
|
10
|
-
Rake.application.remove_task(task_name)
|
3
|
+
%w[db:drop db:create db:abort_if_pending_migrations db:reset].each do |name|
|
4
|
+
Rake.application.instance_variable_get(:@tasks).delete(name) || warn("could not delete #{name} task, potential load-order problem")
|
11
5
|
end
|
12
6
|
|
13
|
-
remove_task 'db:drop'
|
14
|
-
remove_task 'db:create'
|
15
|
-
remove_task 'db:abort_if_pending_migrations'
|
16
|
-
remove_task 'db:reset'
|
17
|
-
|
18
7
|
namespace :db do
|
19
8
|
desc 'Drops the database for the current RAILS_ENV including shards and slaves'
|
20
9
|
task :drop => :load_config do
|
21
10
|
env_name = defined?(Rails.env) ? Rails.env : RAILS_ENV || 'development'
|
22
11
|
ActiveRecord::Base.configurations.each do |key, conf|
|
23
12
|
if key.starts_with?(env_name) && !key.ends_with?("_slave")
|
24
|
-
|
13
|
+
begin
|
14
|
+
drop_database(conf)
|
15
|
+
rescue Exception => e
|
16
|
+
puts "Couldn't drop #{conf['database']} : #{e.inspect}"
|
17
|
+
end
|
25
18
|
end
|
26
19
|
end
|
27
20
|
end
|
@@ -46,22 +46,30 @@ class ConnectionSwitchingTest < ActiveSupport::TestCase
|
|
46
46
|
@shard_0_master = ActiveRecord::Base.on_shard(0) {ActiveRecord::Base.connection}
|
47
47
|
@shard_1_master = ActiveRecord::Base.on_shard(1) {ActiveRecord::Base.connection}
|
48
48
|
assert_not_equal(@shard_0_master.select_value("SELECT DATABASE()"), @shard_1_master.select_value("SELECT DATABASE()"))
|
49
|
+
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
@database_names << ActiveRecord::Base.connection.select_value("SELECT DATABASE()")
|
54
|
-
@database_shards << shard
|
51
|
+
should "execute the block on all shard masters" do
|
52
|
+
result = ActiveRecord::Base.on_all_shards do |shard|
|
53
|
+
[ActiveRecord::Base.connection.select_value("SELECT DATABASE()"), shard]
|
55
54
|
end
|
55
|
+
database_names = result.map(&:first)
|
56
|
+
database_shards = result.map(&:last)
|
57
|
+
|
58
|
+
assert_equal(2, database_names.size)
|
59
|
+
assert_contains(database_names, @shard_0_master.select_value("SELECT DATABASE()"))
|
60
|
+
assert_contains(database_names, @shard_1_master.select_value("SELECT DATABASE()"))
|
61
|
+
|
62
|
+
assert_equal(2, database_shards.size)
|
63
|
+
assert_contains(database_shards, "0")
|
64
|
+
assert_contains(database_shards, "1")
|
56
65
|
end
|
57
66
|
|
58
|
-
should "execute the block
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
assert_contains(@database_shards, "1")
|
67
|
+
should "execute the block unsharded" do
|
68
|
+
ActiveRecord::Base.expects(:supports_sharding?).returns false
|
69
|
+
result = ActiveRecord::Base.on_all_shards do |shard|
|
70
|
+
[ActiveRecord::Base.connection.select_value("SELECT DATABASE()"), shard]
|
71
|
+
end
|
72
|
+
assert_equal [["ars_test", nil]], result
|
65
73
|
end
|
66
74
|
end
|
67
75
|
end
|
@@ -322,6 +330,18 @@ class ConnectionSwitchingTest < ActiveSupport::TestCase
|
|
322
330
|
end
|
323
331
|
end
|
324
332
|
|
333
|
+
context "a inherited model without cached columns hash" do
|
334
|
+
# before columns -> with_scope -> type-condition -> columns == loop
|
335
|
+
should "not loop when on slave by default" do
|
336
|
+
Person.on_slave_by_default = true
|
337
|
+
assert User.on_slave_by_default?
|
338
|
+
assert User.finder_needs_type_condition?
|
339
|
+
|
340
|
+
User.instance_variable_set(:@columns_hash, nil)
|
341
|
+
User.columns_hash
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
325
345
|
context "a model loaded with the master" do
|
326
346
|
setup do
|
327
347
|
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')")
|
data/test/models.rb
CHANGED
data/test/schema.rb
CHANGED
@@ -21,4 +21,11 @@ ActiveRecord::Schema.define(:version => 1) do
|
|
21
21
|
t.datetime "created_at"
|
22
22
|
t.datetime "updated_at"
|
23
23
|
end
|
24
|
+
|
25
|
+
create_table "people", :force => true do |t|
|
26
|
+
t.string "name"
|
27
|
+
t.string "type"
|
28
|
+
t.datetime "created_at"
|
29
|
+
t.datetime "updated_at"
|
30
|
+
end
|
24
31
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_shards
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.6.
|
4
|
+
version: 2.6.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-01-
|
14
|
+
date: 2013-01-16 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: activerecord
|
@@ -242,7 +242,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
242
242
|
version: '0'
|
243
243
|
segments:
|
244
244
|
- 0
|
245
|
-
hash: -
|
245
|
+
hash: -349916606155063800
|
246
246
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
247
247
|
none: false
|
248
248
|
requirements:
|
@@ -251,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
251
251
|
version: '0'
|
252
252
|
segments:
|
253
253
|
- 0
|
254
|
-
hash: -
|
254
|
+
hash: -349916606155063800
|
255
255
|
requirements: []
|
256
256
|
rubyforge_project:
|
257
257
|
rubygems_version: 1.8.24
|