db-charmer 1.8.4 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/CHANGES +19 -0
- data/README.rdoc +12 -537
- data/lib/db_charmer.rb +17 -52
- data/lib/db_charmer/active_record/class_attributes.rb +42 -27
- data/lib/db_charmer/active_record/connection_switching.rb +17 -14
- data/lib/db_charmer/active_record/db_magic.rb +3 -2
- data/lib/db_charmer/connection_factory.rb +13 -5
- data/lib/db_charmer/connection_proxy.rb +30 -1
- data/lib/db_charmer/force_slave_reads.rb +27 -8
- data/lib/db_charmer/sharding/stub_connection.rb +6 -0
- data/lib/db_charmer/version.rb +2 -2
- data/lib/db_charmer/with_remapped_databases.rb +49 -0
- data/lib/tasks/databases.rake +5 -1
- metadata +14 -26
data/lib/db_charmer.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require 'active_record/version' unless defined?(::ActiveRecord::VERSION::MAJOR)
|
3
3
|
require 'active_support/core_ext'
|
4
4
|
|
5
|
+
#---------------------------------------------------------------------------------------------------
|
5
6
|
module DbCharmer
|
6
7
|
# Configure autoload
|
7
8
|
autoload :Sharding, 'db_charmer/sharding'
|
@@ -68,64 +69,33 @@ module DbCharmer
|
|
68
69
|
::ActionController::Base.extend(DbCharmer::ActionController::ForceSlaveReads::ClassMethods)
|
69
70
|
::ActionController::Base.send(:include, DbCharmer::ActionController::ForceSlaveReads::InstanceMethods)
|
70
71
|
end
|
71
|
-
|
72
|
-
#-------------------------------------------------------------------------------------------------
|
73
|
-
def self.with_remapped_databases(mappings, &proc)
|
74
|
-
old_mappings = ::ActiveRecord::Base.db_charmer_database_remappings
|
75
|
-
begin
|
76
|
-
::ActiveRecord::Base.db_charmer_database_remappings = mappings
|
77
|
-
if mappings[:master] || mappings['master']
|
78
|
-
with_all_hijacked(&proc)
|
79
|
-
else
|
80
|
-
proc.call
|
81
|
-
end
|
82
|
-
ensure
|
83
|
-
::ActiveRecord::Base.db_charmer_database_remappings = old_mappings
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def self.hijack_new_classes?
|
88
|
-
@@hijack_new_classes
|
89
|
-
end
|
90
|
-
|
91
|
-
private
|
92
|
-
|
93
|
-
@@hijack_new_classes = false
|
94
|
-
def self.with_all_hijacked
|
95
|
-
old_hijack_new_classes = @@hijack_new_classes
|
96
|
-
begin
|
97
|
-
@@hijack_new_classes = true
|
98
|
-
subclasses_method = DbCharmer.rails3? ? :descendants : :subclasses
|
99
|
-
::ActiveRecord::Base.send(subclasses_method).each do |subclass|
|
100
|
-
subclass.hijack_connection!
|
101
|
-
end
|
102
|
-
yield
|
103
|
-
ensure
|
104
|
-
@@hijack_new_classes = old_hijack_new_classes
|
105
|
-
end
|
106
|
-
end
|
107
72
|
end
|
108
73
|
|
109
74
|
#---------------------------------------------------------------------------------------------------
|
110
75
|
# Print warning about the broken Rails 2.3.4
|
111
76
|
puts "WARNING: Rails 3.2.4 is not officially supported by DbCharmer. Please upgrade." if DbCharmer.rails324?
|
112
77
|
|
78
|
+
#---------------------------------------------------------------------------------------------------
|
113
79
|
# Add useful methods to global object
|
114
80
|
require 'db_charmer/core_extensions'
|
115
81
|
|
116
82
|
require 'db_charmer/connection_factory'
|
117
83
|
require 'db_charmer/connection_proxy'
|
118
84
|
require 'db_charmer/force_slave_reads'
|
85
|
+
require 'db_charmer/with_remapped_databases'
|
119
86
|
|
87
|
+
#---------------------------------------------------------------------------------------------------
|
120
88
|
# Add our custom class-level attributes to AR models
|
121
89
|
require 'db_charmer/active_record/class_attributes'
|
122
90
|
require 'active_record'
|
123
91
|
ActiveRecord::Base.extend(DbCharmer::ActiveRecord::ClassAttributes)
|
124
92
|
|
93
|
+
#---------------------------------------------------------------------------------------------------
|
125
94
|
# Enable connections switching in AR
|
126
95
|
require 'db_charmer/active_record/connection_switching'
|
127
96
|
ActiveRecord::Base.extend(DbCharmer::ActiveRecord::ConnectionSwitching)
|
128
97
|
|
98
|
+
#---------------------------------------------------------------------------------------------------
|
129
99
|
# Enable AR logging extensions
|
130
100
|
if DbCharmer.rails3?
|
131
101
|
require 'db_charmer/rails3/abstract_adapter/connection_name'
|
@@ -137,12 +107,14 @@ else
|
|
137
107
|
ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, DbCharmer::AbstractAdapter::LogFormatting)
|
138
108
|
end
|
139
109
|
|
110
|
+
#---------------------------------------------------------------------------------------------------
|
140
111
|
# Enable connection proxy in AR
|
141
112
|
require 'db_charmer/active_record/multi_db_proxy'
|
142
113
|
ActiveRecord::Base.extend(DbCharmer::ActiveRecord::MultiDbProxy::ClassMethods)
|
143
114
|
ActiveRecord::Base.extend(DbCharmer::ActiveRecord::MultiDbProxy::MasterSlaveClassMethods)
|
144
115
|
ActiveRecord::Base.send(:include, DbCharmer::ActiveRecord::MultiDbProxy::InstanceMethods)
|
145
116
|
|
117
|
+
#---------------------------------------------------------------------------------------------------
|
146
118
|
# Enable connection proxy for relations
|
147
119
|
if DbCharmer.rails3?
|
148
120
|
require 'db_charmer/rails3/active_record/relation_method'
|
@@ -151,15 +123,19 @@ if DbCharmer.rails3?
|
|
151
123
|
ActiveRecord::Relation.send(:include, DbCharmer::ActiveRecord::Relation::ConnectionRouting)
|
152
124
|
end
|
153
125
|
|
126
|
+
#---------------------------------------------------------------------------------------------------
|
154
127
|
# Enable connection proxy for scopes (rails 2.x only)
|
155
128
|
if DbCharmer.rails2?
|
156
129
|
require 'db_charmer/rails2/active_record/named_scope/scope_proxy'
|
157
130
|
ActiveRecord::NamedScope::Scope.send(:include, DbCharmer::ActiveRecord::NamedScope::ScopeProxy)
|
158
131
|
end
|
159
132
|
|
133
|
+
#---------------------------------------------------------------------------------------------------
|
160
134
|
# Enable connection proxy for associations
|
161
|
-
# WARNING: Inject methods to association class right here
|
162
|
-
|
135
|
+
# WARNING: Inject methods to association class right here because they proxy +include+ calls
|
136
|
+
# somewhere else, which means we could not use +include+ method here
|
137
|
+
association_proxy_class = DbCharmer.rails31? ? ActiveRecord::Associations::CollectionProxy :
|
138
|
+
ActiveRecord::Associations::AssociationProxy
|
163
139
|
association_proxy_class.class_eval do
|
164
140
|
def proxy?
|
165
141
|
true
|
@@ -194,6 +170,7 @@ association_proxy_class.class_eval do
|
|
194
170
|
end
|
195
171
|
end
|
196
172
|
|
173
|
+
#---------------------------------------------------------------------------------------------------
|
197
174
|
# Enable multi-db migrations
|
198
175
|
require 'db_charmer/active_record/migration/multi_db_migrations'
|
199
176
|
ActiveRecord::Migration.send(:include, DbCharmer::ActiveRecord::Migration::MultiDbMigrations)
|
@@ -203,6 +180,7 @@ if DbCharmer.rails31?
|
|
203
180
|
ActiveRecord::Migration::CommandRecorder.send(:include, DbCharmer::ActiveRecord::Migration::CommandRecorder)
|
204
181
|
end
|
205
182
|
|
183
|
+
#---------------------------------------------------------------------------------------------------
|
206
184
|
# Enable the magic
|
207
185
|
if DbCharmer.rails3?
|
208
186
|
require 'db_charmer/rails3/active_record/master_slave_routing'
|
@@ -214,6 +192,7 @@ require 'db_charmer/active_record/sharding'
|
|
214
192
|
require 'db_charmer/active_record/db_magic'
|
215
193
|
ActiveRecord::Base.extend(DbCharmer::ActiveRecord::DbMagic)
|
216
194
|
|
195
|
+
#---------------------------------------------------------------------------------------------------
|
217
196
|
# Setup association preload magic
|
218
197
|
if DbCharmer.rails31?
|
219
198
|
require 'db_charmer/rails31/active_record/preloader/association'
|
@@ -227,17 +206,3 @@ else
|
|
227
206
|
# Open up really useful API method
|
228
207
|
ActiveRecord::AssociationPreload::ClassMethods.send(:public, :preload_associations)
|
229
208
|
end
|
230
|
-
|
231
|
-
#---------------------------------------------------------------------------------------------------
|
232
|
-
# Hijack connection on all new AR classes when we're in a block with main AR connection remapped
|
233
|
-
class ActiveRecord::Base
|
234
|
-
class << self
|
235
|
-
def inherited_with_hijacking(subclass)
|
236
|
-
out = inherited_without_hijacking(subclass)
|
237
|
-
hijack_connection! if DbCharmer.hijack_new_classes?
|
238
|
-
out
|
239
|
-
end
|
240
|
-
|
241
|
-
alias_method_chain :inherited, :hijacking
|
242
|
-
end
|
243
|
-
end
|
@@ -10,17 +10,7 @@ module DbCharmer
|
|
10
10
|
@@db_charmer_opts[self.name] || {}
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
@@db_charmer_connection_proxies = {}
|
15
|
-
def db_charmer_connection_proxy=(proxy)
|
16
|
-
@@db_charmer_connection_proxies[self.name] = proxy
|
17
|
-
end
|
18
|
-
|
19
|
-
def db_charmer_connection_proxy
|
20
|
-
@@db_charmer_connection_proxies[self.name]
|
21
|
-
end
|
22
|
-
|
23
|
-
#-----------------------------------------------------------------------------
|
13
|
+
#---------------------------------------------------------------------------------------------
|
24
14
|
@@db_charmer_default_connections = {}
|
25
15
|
def db_charmer_default_connection=(conn)
|
26
16
|
@@db_charmer_default_connections[self.name] = conn
|
@@ -30,7 +20,7 @@ module DbCharmer
|
|
30
20
|
@@db_charmer_default_connections[self.name]
|
31
21
|
end
|
32
22
|
|
33
|
-
|
23
|
+
#---------------------------------------------------------------------------------------------
|
34
24
|
@@db_charmer_slaves = {}
|
35
25
|
def db_charmer_slaves=(slaves)
|
36
26
|
@@db_charmer_slaves[self.name] = slaves
|
@@ -40,19 +30,36 @@ module DbCharmer
|
|
40
30
|
@@db_charmer_slaves[self.name] || []
|
41
31
|
end
|
42
32
|
|
33
|
+
# Returns a random connection from the list of slaves configured for this AR class
|
43
34
|
def db_charmer_random_slave
|
44
35
|
return nil unless db_charmer_slaves.any?
|
45
36
|
db_charmer_slaves[rand(db_charmer_slaves.size)]
|
46
37
|
end
|
47
38
|
|
48
|
-
|
49
|
-
|
39
|
+
#---------------------------------------------------------------------------------------------
|
40
|
+
def db_charmer_connection_proxies
|
41
|
+
Thread.current[:db_charmer_connection_proxies] ||= {}
|
42
|
+
end
|
43
|
+
|
44
|
+
def db_charmer_connection_proxy=(proxy)
|
45
|
+
db_charmer_connection_proxies[self.name] = proxy
|
46
|
+
end
|
47
|
+
|
48
|
+
def db_charmer_connection_proxy
|
49
|
+
db_charmer_connection_proxies[self.name]
|
50
|
+
end
|
51
|
+
|
52
|
+
#---------------------------------------------------------------------------------------------
|
53
|
+
def db_charmer_force_slave_reads_flags
|
54
|
+
Thread.current[:db_charmer_force_slave_reads] ||= {}
|
55
|
+
end
|
56
|
+
|
50
57
|
def db_charmer_force_slave_reads=(force)
|
51
|
-
|
58
|
+
db_charmer_force_slave_reads_flags[self.name] = force
|
52
59
|
end
|
53
60
|
|
54
61
|
def db_charmer_force_slave_reads
|
55
|
-
|
62
|
+
db_charmer_force_slave_reads_flags[self.name]
|
56
63
|
end
|
57
64
|
|
58
65
|
# Slave reads are used in two cases:
|
@@ -62,39 +69,47 @@ module DbCharmer
|
|
62
69
|
db_charmer_force_slave_reads || DbCharmer.force_slave_reads?
|
63
70
|
end
|
64
71
|
|
65
|
-
|
66
|
-
|
72
|
+
#---------------------------------------------------------------------------------------------
|
73
|
+
def db_charmer_connection_levels
|
74
|
+
Thread.current[:db_charmer_connection_levels] ||= Hash.new(0)
|
75
|
+
end
|
76
|
+
|
67
77
|
def db_charmer_connection_level=(level)
|
68
|
-
|
78
|
+
db_charmer_connection_levels[self.name] = level
|
69
79
|
end
|
70
80
|
|
71
81
|
def db_charmer_connection_level
|
72
|
-
|
82
|
+
db_charmer_connection_levels[self.name] || 0
|
73
83
|
end
|
74
84
|
|
75
85
|
def db_charmer_top_level_connection?
|
76
86
|
db_charmer_connection_level.zero?
|
77
87
|
end
|
78
88
|
|
79
|
-
|
80
|
-
@@db_charmer_database_remappings = Hash.new
|
89
|
+
#---------------------------------------------------------------------------------------------
|
81
90
|
def db_charmer_remapped_connection
|
82
|
-
return nil
|
91
|
+
return nil unless db_charmer_top_level_connection?
|
83
92
|
name = :master
|
84
|
-
proxy =
|
93
|
+
proxy = db_charmer_model_connection_proxy
|
85
94
|
name = proxy.db_charmer_connection_name.to_sym if proxy
|
86
95
|
|
87
|
-
remapped =
|
96
|
+
remapped = db_charmer_database_remappings[name]
|
88
97
|
remapped ? DbCharmer::ConnectionFactory.connect(remapped, true) : nil
|
89
98
|
end
|
90
99
|
|
91
100
|
def db_charmer_database_remappings
|
92
|
-
|
101
|
+
Thread.current[:db_charmer_database_remappings] ||= Hash.new
|
93
102
|
end
|
94
103
|
|
95
104
|
def db_charmer_database_remappings=(mappings)
|
96
105
|
raise "Mappings must be nil or respond to []" if mappings && (! mappings.respond_to?(:[]))
|
97
|
-
|
106
|
+
Thread.current[:db_charmer_database_remappings] = mappings || {}
|
107
|
+
end
|
108
|
+
|
109
|
+
#---------------------------------------------------------------------------------------------
|
110
|
+
# Returns model-specific connection proxy, ignoring any global connection remappings
|
111
|
+
def db_charmer_model_connection_proxy
|
112
|
+
db_charmer_connection_proxy || db_charmer_default_connection
|
98
113
|
end
|
99
114
|
end
|
100
115
|
end
|
@@ -31,13 +31,13 @@ module DbCharmer
|
|
31
31
|
class << self
|
32
32
|
# Make sure we check our accessors before going to the default connection retrieval method
|
33
33
|
def connection_with_magic
|
34
|
-
db_charmer_remapped_connection ||
|
34
|
+
db_charmer_remapped_connection || db_charmer_model_connection_proxy || connection_without_magic
|
35
35
|
end
|
36
36
|
alias_method_chain :connection, :magic
|
37
37
|
|
38
38
|
def connection_pool_with_magic
|
39
|
-
|
40
|
-
|
39
|
+
if connection.respond_to?(:abstract_connection_class)
|
40
|
+
abstract_connection_class = connection.abstract_connection_class
|
41
41
|
connection_handler.retrieve_connection_pool(abstract_connection_class) || connection_pool_without_magic
|
42
42
|
else
|
43
43
|
connection_pool_without_magic
|
@@ -49,26 +49,31 @@ module DbCharmer
|
|
49
49
|
|
50
50
|
#-----------------------------------------------------------------------------------------------------------------
|
51
51
|
def coerce_to_connection_proxy(conn, should_exist = true)
|
52
|
+
# Return nil if given no connection specification
|
52
53
|
return nil if conn.nil?
|
53
54
|
|
55
|
+
# For sharded proxies just use them as-is
|
56
|
+
return conn if conn.respond_to?(:set_real_connection)
|
57
|
+
|
58
|
+
# For connection proxies and objects that could be coerced into a proxy just call the coercion method
|
59
|
+
return conn.db_charmer_connection_proxy if conn.respond_to?(:db_charmer_connection_proxy)
|
60
|
+
|
61
|
+
# For plain AR connection adapters, just use them as-is
|
62
|
+
return conn if conn.kind_of?(::ActiveRecord::ConnectionAdapters::AbstractAdapter)
|
63
|
+
|
64
|
+
# For connection names, use connection factory to create new connections
|
54
65
|
if conn.kind_of?(Symbol) || conn.kind_of?(String)
|
55
66
|
return DbCharmer::ConnectionFactory.connect(conn, should_exist)
|
56
67
|
end
|
57
68
|
|
69
|
+
# For connection configs (hashes), create connections
|
58
70
|
if conn.kind_of?(Hash)
|
59
71
|
conn = conn.symbolize_keys
|
60
72
|
raise ArgumentError, "Missing required :connection_name parameter" unless conn[:connection_name]
|
61
73
|
return DbCharmer::ConnectionFactory.connect_to_db(conn[:connection_name], conn)
|
62
74
|
end
|
63
75
|
|
64
|
-
|
65
|
-
return conn.db_charmer_connection_proxy
|
66
|
-
end
|
67
|
-
|
68
|
-
if conn.kind_of?(::ActiveRecord::ConnectionAdapters::AbstractAdapter) || conn.kind_of?(DbCharmer::Sharding::StubConnection)
|
69
|
-
return conn
|
70
|
-
end
|
71
|
-
|
76
|
+
# Fails for unsupported connection types
|
72
77
|
raise "Unsupported connection type: #{conn.class}"
|
73
78
|
end
|
74
79
|
|
@@ -76,14 +81,12 @@ module DbCharmer
|
|
76
81
|
def switch_connection_to(conn, should_exist = true)
|
77
82
|
new_conn = coerce_to_connection_proxy(conn, should_exist)
|
78
83
|
|
79
|
-
if db_charmer_connection_proxy.
|
84
|
+
if db_charmer_connection_proxy.respond_to?(:set_real_connection)
|
80
85
|
db_charmer_connection_proxy.set_real_connection(new_conn)
|
81
86
|
end
|
82
87
|
|
83
88
|
self.db_charmer_connection_proxy = new_conn
|
84
89
|
self.hijack_connection!
|
85
|
-
|
86
|
-
# self.reset_column_information
|
87
90
|
end
|
88
91
|
|
89
92
|
end
|
@@ -64,8 +64,9 @@ module DbCharmer
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def setup_connection_magic(conn, should_exist = true)
|
67
|
-
|
68
|
-
self.db_charmer_default_connection =
|
67
|
+
conn_proxy = coerce_to_connection_proxy(conn, should_exist)
|
68
|
+
self.db_charmer_default_connection = conn_proxy
|
69
|
+
switch_connection_to(conn_proxy, should_exist)
|
69
70
|
end
|
70
71
|
|
71
72
|
def setup_slaves_magic(slaves, force_slave_reads, should_exist = true)
|
@@ -6,22 +6,28 @@
|
|
6
6
|
#
|
7
7
|
module DbCharmer
|
8
8
|
module ConnectionFactory
|
9
|
-
|
9
|
+
def self.connection_classes
|
10
|
+
Thread.current[:db_charmer_generated_connection_classes] ||= {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.connection_classes=(val)
|
14
|
+
Thread.current[:db_charmer_generated_connection_classes] = val
|
15
|
+
end
|
10
16
|
|
11
17
|
def self.reset!
|
12
|
-
|
18
|
+
self.connection_classes = {}
|
13
19
|
end
|
14
20
|
|
15
21
|
# Establishes connection or return an existing one from cache
|
16
22
|
def self.connect(connection_name, should_exist = true)
|
17
23
|
connection_name = connection_name.to_s
|
18
|
-
|
24
|
+
connection_classes[connection_name] ||= establish_connection(connection_name, should_exist)
|
19
25
|
end
|
20
26
|
|
21
27
|
# Establishes connection or return an existing one from cache (not using AR database configs)
|
22
28
|
def self.connect_to_db(connection_name, config)
|
23
29
|
connection_name = connection_name.to_s
|
24
|
-
|
30
|
+
connection_classes[connection_name] ||= establish_connection_to_db(connection_name, config)
|
25
31
|
end
|
26
32
|
|
27
33
|
# Establish connection with a specified name
|
@@ -70,7 +76,9 @@ module DbCharmer
|
|
70
76
|
|
71
77
|
# Generates unique names for our abstract AR classes
|
72
78
|
def self.abstract_connection_class_name(connection_name)
|
73
|
-
|
79
|
+
conn_name_klass = connection_name.to_s.gsub(/\W+/, '_').camelize
|
80
|
+
thread = Thread.current.object_id.abs # need to make sure it is non-negative
|
81
|
+
"::AutoGeneratedAbstractConnectionClass#{conn_name_klass}ForThread#{thread}"
|
74
82
|
end
|
75
83
|
end
|
76
84
|
end
|
@@ -20,8 +20,37 @@ module DbCharmer
|
|
20
20
|
self
|
21
21
|
end
|
22
22
|
|
23
|
+
def db_charmer_retrieve_connection
|
24
|
+
@abstract_connection_class.retrieve_connection
|
25
|
+
end
|
26
|
+
|
27
|
+
def nil?
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
#-----------------------------------------------------------------------------------------------
|
32
|
+
RESPOND_TO_METHODS = [
|
33
|
+
:abstract_connection_class,
|
34
|
+
:db_charmer_connection_name,
|
35
|
+
:db_charmer_connection_proxy,
|
36
|
+
:db_charmer_retrieve_connection,
|
37
|
+
:nil?
|
38
|
+
].freeze
|
39
|
+
|
40
|
+
# Short-circuit some of the methods for which we know there is a separate check in coercion code
|
41
|
+
DOESNT_RESPOND_TO_METHODS = [
|
42
|
+
:set_real_connection
|
43
|
+
].freeze
|
44
|
+
|
45
|
+
def respond_to?(method_name, include_all = false)
|
46
|
+
return true if RESPOND_TO_METHODS.include?(method_name)
|
47
|
+
return false if DOESNT_RESPOND_TO_METHODS.include?(method_name)
|
48
|
+
db_charmer_retrieve_connection.respond_to?(method_name, include_all)
|
49
|
+
end
|
50
|
+
|
51
|
+
#-----------------------------------------------------------------------------------------------
|
23
52
|
def method_missing(meth, *args, &block)
|
24
|
-
|
53
|
+
db_charmer_retrieve_connection.send(meth, *args, &block)
|
25
54
|
end
|
26
55
|
end
|
27
56
|
end
|
@@ -1,12 +1,25 @@
|
|
1
1
|
module DbCharmer
|
2
|
-
|
3
|
-
|
2
|
+
def self.current_controller
|
3
|
+
Thread.current[:db_charmer_current_controller]
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.current_controller=(val)
|
7
|
+
Thread.current[:db_charmer_current_controller] = val
|
8
|
+
end
|
9
|
+
|
10
|
+
#-------------------------------------------------------------------------------------------------
|
11
|
+
def self.forced_slave_reads_setting
|
12
|
+
Thread.current[:db_charmer_forced_slave_reads]
|
13
|
+
end
|
4
14
|
|
5
|
-
|
15
|
+
def self.forced_slave_reads_setting=(val)
|
16
|
+
Thread.current[:db_charmer_forced_slave_reads] = val
|
17
|
+
end
|
6
18
|
|
19
|
+
#-------------------------------------------------------------------------------------------------
|
7
20
|
def self.force_slave_reads?
|
8
21
|
# If global force slave reads is requested, do it
|
9
|
-
return
|
22
|
+
return true if Thread.current[:db_charmer_forced_slave_reads]
|
10
23
|
|
11
24
|
# If not, try to use current controller to decide on this
|
12
25
|
return false unless current_controller.respond_to?(:force_slave_reads?)
|
@@ -16,6 +29,7 @@ module DbCharmer
|
|
16
29
|
return slave_reads
|
17
30
|
end
|
18
31
|
|
32
|
+
#-------------------------------------------------------------------------------------------------
|
19
33
|
def self.with_controller(controller)
|
20
34
|
raise ArgumentError, "No block given" unless block_given?
|
21
35
|
logger.debug("Setting current controller for db_charmer: #{controller.class.name}")
|
@@ -26,11 +40,16 @@ module DbCharmer
|
|
26
40
|
self.current_controller = nil
|
27
41
|
end
|
28
42
|
|
43
|
+
#-------------------------------------------------------------------------------------------------
|
44
|
+
# Force all reads in a block of code to go to a slave
|
29
45
|
def self.force_slave_reads
|
30
46
|
raise ArgumentError, "No block given" unless block_given?
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
47
|
+
old_forced_slave_reads = self.forced_slave_reads_setting
|
48
|
+
begin
|
49
|
+
self.forced_slave_reads_setting = true
|
50
|
+
yield
|
51
|
+
ensure
|
52
|
+
self.forced_slave_reads_setting = old_forced_slave_reads
|
53
|
+
end
|
35
54
|
end
|
36
55
|
end
|