active_record_shards 2.6.6 → 2.6.7
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.
- 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
|