fresh_connection 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bb171789539cc2eaf31793f904e53f4c0a9f1114
4
+ data.tar.gz: be8ef001eec63ca7a879d3950fb460b7f300bdb6
5
+ SHA512:
6
+ metadata.gz: becd1aed70d40cecaa8155630609e7ec13d9fd62c4f4ce6fb92e4f6e54bdeb025915aa55dc9deb226da2a89f6c0bfb491353dea84b68595bf015599108c8e238
7
+ data.tar.gz: 4aa63bc28708181c47df8dfd211e6fceb2df57dc2a45d1e053a0594db9d1b82b6d366c0186c77f17f1b8faa80a5fccd26f4d9aa8fe51a88b9a9b0451aee32fcf
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in n_adic_number.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 tsukasaoishi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # FreshConnection
2
+
3
+ FreshConnection supports to connect with Mysql slave servers via Load Balancers.
4
+ All connections will be disconnected every time at the end of the action.
5
+
6
+ ## Installation
7
+
8
+ ### For Rails3
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem "fresh_connection"
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install fresh_connection
20
+
21
+ ### For Rails2.3
22
+
23
+ $ gem install fresh_connection -v 0.0.7
24
+
25
+ ## Config
26
+ #### config/database.yml
27
+
28
+ production:
29
+ adapter: mysql2
30
+ encoding: utf8
31
+ reconnect: true
32
+ database: kaeru
33
+ pool: 5
34
+ username: master
35
+ password: master
36
+ host: localhost
37
+ socket: /var/run/mysqld/mysqld.sock
38
+
39
+ slave:
40
+ username: slave
41
+ password: slave
42
+ host: slave
43
+
44
+ slave is config to connect to slave servers.
45
+ Others will use the master setting. If you want to change, write in the slave.
46
+
47
+ ### config/initializers/fresh_connection.rb
48
+
49
+ FreshConnection::SlaveConnection.ignore_models = %w|Model1 Model2|
50
+
51
+ If models that ignore access to slave servers is exist, You can write model name at FreshConnection::SlaveConnection.ignore models.
52
+
53
+ ### use config/environment.rb if rails2.3
54
+
55
+ require 'fresh_connection'
56
+ ActionController::Dispatcher.middleware.swap ActiveRecord::ConnectionAdapters::ConnectionManagement, FreshConnection::Rack::ConnectionManagement
57
+
58
+ ## Usage
59
+ Read query will be access to slave server.
60
+
61
+ Article.where(:id => 1)
62
+
63
+ If you want to access to master saver, use readonly(false).
64
+
65
+ Article.where(:id => 1).readonly(false)
66
+
67
+ In transaction, Always will be access to master server.
68
+
69
+ Article.transaction do
70
+ Article.where(:id => 1)
71
+ end
72
+
73
+
74
+ ## Contributing
75
+
76
+ 1. Fork it
77
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
78
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
79
+ 4. Push to the branch (`git push origin my-new-feature`)
80
+ 5. Create new Pull Request
data/Rakefile CHANGED
@@ -1,27 +1 @@
1
- %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
- require File.dirname(__FILE__) + '/lib/fresh_connection'
3
-
4
- # Generate all the Rake tasks
5
- # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
- $hoe = Hoe.new('fresh_connection', FreshConnection::VERSION) do |p|
7
- p.developer('Tsukasa OISHI', 'tsukasa.oishi@gmail.com')
8
- p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
- p.rubyforge_name = p.name # TODO this is default value
10
- # p.extra_deps = [
11
- # ['activesupport','>= 2.0.2'],
12
- # ]
13
- p.extra_dev_deps = [
14
- ['newgem', ">= #{::Newgem::VERSION}"]
15
- ]
16
-
17
- p.clean_globs |= %w[**/.DS_Store tmp *.log]
18
- path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
19
- p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
20
- p.rsync_args = '-av --delete --ignore-errors'
21
- end
22
-
23
- require 'newgem/tasks' # load /tasks/*.rake
24
- Dir['tasks/**/*.rake'].each { |t| load t }
25
-
26
- # TODO - want other tests/tasks run by default? Add them to the list
27
- # task :default => [:spec, :features]
1
+ require "bundler/gem_tasks"
@@ -1,28 +1,25 @@
1
- # -*- encoding: utf-8 -*-
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fresh_connection/version'
2
5
 
3
- Gem::Specification.new do |s|
4
- s.name = %q{fresh_connection}
5
- s.version = "0.0.7"
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "fresh_connection"
8
+ spec.version = FreshConnection::VERSION
9
+ spec.authors = ["Tsukasa OISHI"]
10
+ spec.email = ["tsukasa.oishi@gmail.com"]
11
+ spec.description = %q{https://github.com/tsukasaoishi/fresh_connection}
12
+ spec.summary = %q{FreshConnection supports to connect with Mysql slave servers via Load Balancers.}
13
+ spec.homepage = "https://github.com/tsukasaoishi/fresh_connection"
14
+ spec.license = "MIT"
6
15
 
7
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Tsukasa OISHI"]
9
- s.date = %q{2010-10-16}
10
- s.description = %q{FreshConnection supports of connect with Mysql slave servers via Load Balancers.}
11
- s.email = ["tsukasa.oishi@gmail.com"]
12
- s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
13
- s.files = %w|
14
- Rakefile
15
- fresh_connection.gemspec
16
- lib/fresh_connection.rb
17
- lib/fresh_connection/slave_connection.rb
18
- lib/fresh_connection/rack/connection_management.rb
19
- rails/initializers/active_record_base.rb
20
- |
21
- s.has_rdoc = true
22
- s.homepage = %q{https://github.com/tsukasaoishi/fresh_connection}
23
- s.rdoc_options = ["--main", "README.rdoc"]
24
- s.require_paths = ["lib"]
25
- s.rubyforge_project = %q{fresh_connection}
26
- s.rubygems_version = %q{1.3.1}
27
- s.summary = %q{FreshConnection supports of connect with Mysql slave servers via Load Balancers.}
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'activerecord', '~> 3.2.0'
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
28
25
  end
@@ -0,0 +1,24 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class AbstractAdapter
4
+ def select_all_with_slave_connection(arel, name = nil, binds = [])
5
+ if FreshConnection::SlaveConnection.slave_access?
6
+ change_connection {select_all_without_slave_connection(arel, "[slave] #{name}", binds)}
7
+ else
8
+ select_all_without_slave_connection(arel, name, binds)
9
+ end
10
+ end
11
+ alias_method_chain :select_all, :slave_connection
12
+
13
+ private
14
+
15
+ def change_connection
16
+ master_con, @connection =
17
+ @connection, FreshConnection::SlaveConnection.connection.raw_connection
18
+ yield
19
+ ensure
20
+ @connection = master_con
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,14 @@
1
+ require 'active_record/connection_adapters/mysql2_adapter'
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ class Mysql2Adapter < AbstractMysqlAdapter
6
+ private
7
+
8
+ def configure_connection_with_ignore
9
+ configure_connection_without_ignore unless FreshConnection::SlaveConnection.ignore_configure_connection?
10
+ end
11
+ alias_method_chain :configure_connection, :ignore
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ module ActiveRecord
2
+ class Relation
3
+ private
4
+
5
+ def exec_queries_with_slave_connection
6
+ return @records if loaded?
7
+
8
+ if FreshConnection::SlaveConnection.ignore_model?(@klass.name)
9
+ FreshConnection::SlaveConnection.force_master_access { exec_queries_without_slave_connection }
10
+ elsif go_slave?
11
+ FreshConnection::SlaveConnection.slave_access { exec_queries_without_slave_connection }
12
+ else
13
+ FreshConnection::SlaveConnection.master_access { exec_queries_without_slave_connection }
14
+ end
15
+ end
16
+ alias_method_chain :exec_queries, :slave_connection
17
+
18
+ def go_slave?
19
+ connection.open_transactions == 0 && (@readonly_value.nil? || @readonly_value)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,10 @@
1
+ module FreshConnection
2
+ class Railtie < Rails::Railtie
3
+ initializer "fresh_connection.configure_rails_initialization" do |app|
4
+ app.config.middleware.swap(
5
+ ActiveRecord::ConnectionAdapters::ConnectionManagement,
6
+ FreshConnection::Rack::ConnectionManagement
7
+ )
8
+ end
9
+ end
10
+ end
@@ -1,5 +1,8 @@
1
1
  module FreshConnection
2
2
  class SlaveConnection
3
+ COUNT = :fresh_connection_access_count
4
+ TARGET = :fresh_connection_access_target
5
+
3
6
  class << self
4
7
  attr_writer :ignore_models, :ignore_configure_connection, :master_clear_connection
5
8
 
@@ -14,16 +17,30 @@ module FreshConnection
14
17
  @slave_connections = {}
15
18
  end
16
19
 
17
- def slave_access_in
18
- Thread.current[:fresh_connection_slave_access] = true
20
+ def slave_access
21
+ access_in(:slave)
22
+ yield
23
+ ensure
24
+ access_out
25
+ end
26
+
27
+ def master_access
28
+ access_in(:master)
29
+ yield
30
+ ensure
31
+ access_out
19
32
  end
20
33
 
21
- def slave_access_out
22
- Thread.current[:fresh_connection_slave_access] = false
34
+ def force_master_access
35
+ now_target = Thread.current[TARGET]
36
+ Thread.current[TARGET] = :master
37
+ yield
38
+ ensure
39
+ Thread.current[TARGET] = now_target
23
40
  end
24
41
 
25
42
  def slave_access?
26
- Thread.current[:fresh_connection_slave_access] ||= false
43
+ Thread.current[TARGET] == :slave
27
44
  end
28
45
 
29
46
  def ignore_model?(model_name)
@@ -35,20 +52,30 @@ module FreshConnection
35
52
  end
36
53
 
37
54
  def master_clear_connection?
38
- @master_clear_connection.nil? || @master_clear_connection
55
+ @master_clear_connection || false
39
56
  end
40
57
 
41
58
  private
42
59
 
60
+ def access_in(target)
61
+ Thread.current[COUNT] = (Thread.current[COUNT] || 0) + 1
62
+ Thread.current[TARGET] ||= target
63
+ end
64
+
65
+ def access_out
66
+ Thread.current[COUNT] -= 1
67
+ if Thread.current[COUNT] == 0
68
+ Thread.current[TARGET] = nil
69
+ Thread.current[COUNT] = nil
70
+ end
71
+ end
72
+
73
+
43
74
  def slave_connection
44
75
  @slave_connections ||= {}
45
76
  @slave_connections[current_thread_id] ||= new_connection
46
77
  end
47
78
 
48
- def clear_slave_connection
49
- @slave_connections[current_thread_id] = nil
50
- end
51
-
52
79
  def new_connection
53
80
  ActiveRecord::Base.send("#{spec["adapter"]}_connection", spec)
54
81
  end
@@ -0,0 +1,4 @@
1
+ module FreshConnection
2
+ VERSION = "0.1.0"
3
+ end
4
+
@@ -1,8 +1,8 @@
1
- module FreshConnection
2
- VERSION = "0.0.5"
3
- end
4
-
1
+ require "fresh_connection/version"
5
2
  require "fresh_connection/slave_connection"
6
3
  require "fresh_connection/rack/connection_management"
4
+ require "fresh_connection/active_record/relation"
5
+ require "fresh_connection/active_record/abstract_adapter"
6
+ require "fresh_connection/active_record/mysql2_adapter"
7
7
 
8
- Dir.glob("#{File.join(File.dirname(__FILE__), "../rails/initializers")}/*.rb").each{|path| require path}
8
+ require "fresh_connection/railtie.rb" if defined?(Rails)
metadata CHANGED
@@ -1,60 +1,99 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fresh_connection
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
5
- prerelease:
4
+ version: 0.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Tsukasa OISHI
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2010-10-16 00:00:00.000000000 Z
13
- dependencies: []
14
- description: FreshConnection supports of connect with Mysql slave servers via Load
15
- Balancers.
11
+ date: 2013-12-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 3.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: https://github.com/tsukasaoishi/fresh_connection
16
56
  email:
17
57
  - tsukasa.oishi@gmail.com
18
58
  executables: []
19
59
  extensions: []
20
- extra_rdoc_files:
21
- - History.txt
22
- - Manifest.txt
23
- - README.rdoc
60
+ extra_rdoc_files: []
24
61
  files:
62
+ - Gemfile
63
+ - LICENSE.txt
64
+ - README.md
25
65
  - Rakefile
26
66
  - fresh_connection.gemspec
27
67
  - lib/fresh_connection.rb
28
- - lib/fresh_connection/slave_connection.rb
68
+ - lib/fresh_connection/active_record/abstract_adapter.rb
69
+ - lib/fresh_connection/active_record/mysql2_adapter.rb
70
+ - lib/fresh_connection/active_record/relation.rb
29
71
  - lib/fresh_connection/rack/connection_management.rb
30
- - rails/initializers/active_record_base.rb
31
- - History.txt
32
- - Manifest.txt
33
- - README.rdoc
72
+ - lib/fresh_connection/railtie.rb
73
+ - lib/fresh_connection/slave_connection.rb
74
+ - lib/fresh_connection/version.rb
34
75
  homepage: https://github.com/tsukasaoishi/fresh_connection
35
- licenses: []
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
36
79
  post_install_message:
37
- rdoc_options:
38
- - --main
39
- - README.rdoc
80
+ rdoc_options: []
40
81
  require_paths:
41
82
  - lib
42
83
  required_ruby_version: !ruby/object:Gem::Requirement
43
- none: false
44
84
  requirements:
45
- - - ! '>='
85
+ - - '>='
46
86
  - !ruby/object:Gem::Version
47
87
  version: '0'
48
88
  required_rubygems_version: !ruby/object:Gem::Requirement
49
- none: false
50
89
  requirements:
51
- - - ! '>='
90
+ - - '>='
52
91
  - !ruby/object:Gem::Version
53
92
  version: '0'
54
93
  requirements: []
55
- rubyforge_project: fresh_connection
56
- rubygems_version: 1.8.23
94
+ rubyforge_project:
95
+ rubygems_version: 2.0.0
57
96
  signing_key:
58
- specification_version: 3
59
- summary: FreshConnection supports of connect with Mysql slave servers via Load Balancers.
97
+ specification_version: 4
98
+ summary: FreshConnection supports to connect with Mysql slave servers via Load Balancers.
60
99
  test_files: []
data/History.txt DELETED
@@ -1,13 +0,0 @@
1
- == 0.0.1 2011-10-16
2
-
3
- * 1 major enhancement:
4
- * Initial release
5
-
6
- == 0.0.2 2011-10-18
7
-
8
- * Ignore setting support
9
- * Abolish multi connection
10
-
11
- == 0.0.3 2012-05-23
12
-
13
- * Ignore Configure Connection
data/Manifest.txt DELETED
@@ -1,9 +0,0 @@
1
- History.txt
2
- Manifest.txt
3
- README
4
- Rakefile
5
- fresh_connection.gemspec
6
- lib/fresh_connection.rb
7
- lib/fresh_connection/slave_connection.rb
8
- lib/fresh_connection/rack/connection_management.rb
9
- rails/initializers/active_record_base.rb
data/README.rdoc DELETED
@@ -1,60 +0,0 @@
1
- = FreshConnection
2
-
3
- * https://github.com/tsukasaoishi/fresh_connection
4
-
5
- == Description
6
-
7
- FreshConnection supports of connect with Mysql slave servers via Load Balancers.
8
- Currently, I have only tested with Rails2.3.14.
9
- In the future, I plan to support Rails3.
10
-
11
- All connections will be disconnected every time at the end of the action.
12
-
13
- == How to use at Rails
14
-
15
- === Gemfile
16
- gem "fresh_connection", "=0.0.2"
17
-
18
- === config/database.yml
19
- production:
20
- adapter: mysql
21
- encoding: utf8
22
- reconnect: true
23
- database: kaeru
24
- pool: 5
25
- username: master
26
- password: master
27
- host: localhost
28
- socket: /var/run/mysqld/mysqld.sock
29
-
30
- slave:
31
- username: slave
32
- password: slave
33
- host: slave
34
-
35
- slave is config to connect to slave servers.
36
- Others will use the master setting. If you want to change, write in the slave.
37
-
38
-
39
- === config/environment.rb
40
- require 'fresh_connection'
41
- ActionController::Dispatcher.middleware.swap ActiveRecord::ConnectionAdapters::ConnectionManagement, FreshConnection::Rack::ConnectionManagement
42
-
43
- === config/initializers/fresh_connection.rb
44
- FreshConnection::SlaveConnection.ignore_models = %w|Model1 Model2|
45
-
46
- If models that ignore access to slave servers is exist, You can write model name at FreshConnection::SlaveConnection.ignore_models.
47
-
48
- == Synopis
49
- Read query will be access to slave server.
50
- Article.where(:id => 1)
51
-
52
- If you want to access to master saver, use readonly(false).
53
- Article.where(:id => 1).readonly(false)
54
-
55
- In transaction, Always will be access to master server.
56
- Article.transaction do
57
- Article.where(:id => 1)
58
- end
59
-
60
-
@@ -1,109 +0,0 @@
1
- module ActiveRecord
2
- module ConnectionAdapters
3
- class AbstractAdapter
4
- def select_all_with_slave_cluster(*args)
5
- if FreshConnection::SlaveConnection.slave_access?
6
- change_connection {select_all_without_slave_cluster(*args)}
7
- else
8
- select_all_without_slave_cluster(*args)
9
- end
10
- end
11
- alias_method_chain :select_all, :slave_cluster
12
-
13
- def columns_with_slave_cluster(*args)
14
- if FreshConnection::SlaveConnection.slave_access?
15
- change_connection {columns_without_slave_cluster(*args)}
16
- else
17
- columns_without_slave_cluster(*args)
18
- end
19
- end
20
- alias_method_chain :columns, :slave_cluster
21
-
22
- def log_info_with_slave_cluster(sql, name, ms)
23
- name = "[MASTER] " + (name || "SQL") if !FreshConnection::SlaveConnection.slave_access? && name != "CACHE"
24
- log_info_without_slave_cluster(sql, name, ms)
25
- end
26
- alias_method_chain :log_info, :slave_cluster
27
-
28
- private
29
-
30
- def change_connection
31
- master_con, @connection = @connection, FreshConnection::SlaveConnection.connection.raw_connection
32
- yield
33
- ensure
34
- @connection = master_con
35
- end
36
- end
37
-
38
- class MysqlAdapter < AbstractAdapter
39
- private
40
-
41
- def configure_connection_with_ignore
42
- configure_connection_without_ignore unless FreshConnection::SlaveConnection.ignore_configure_connection?
43
- end
44
- alias_method_chain :configure_connection, :ignore
45
- end
46
- end
47
-
48
- class Base
49
- class << self
50
- def find_every_with_slave_cluster(options)
51
- run_on_db(options) { find_every_without_slave_cluster(options) }
52
- end
53
- alias_method_chain :find_every, :slave_cluster
54
-
55
- def find_by_sql_with_slave_cluster(sql, options = nil)
56
- run_on_db(options) { find_by_sql_without_slave_cluster(sql) }
57
- end
58
- alias_method_chain :find_by_sql, :slave_cluster
59
-
60
- def count_by_sql_with_slave_cluster(sql, options = nil)
61
- run_on_db(options) { count_by_sql_without_slave_cluster(sql) }
62
- end
63
- alias_method_chain :count_by_sql, :slave_cluster
64
-
65
- def calculate_with_slave_cluster(operation, column_name, options = {})
66
- run_on_db(options) do
67
- options.delete(:readonly)
68
- calculate_without_slave_cluster(operation, column_name, options)
69
- end
70
- end
71
- alias_method_chain :calculate, :slave_cluster
72
-
73
- private
74
-
75
- def run_on_db(options)
76
- in_run_on_db(options)
77
- run_on_db_status[:go_slave] ? run_on_readonly_db{yield} : yield
78
- ensure
79
- out_run_on_db
80
- end
81
-
82
- def in_run_on_db(options)
83
- run_on_db_status[:go_slave] = go_slave?(options) if run_on_db_status[:count] == 0
84
- run_on_db_status[:count] += 1
85
- end
86
-
87
- def out_run_on_db
88
- run_on_db_status[:count] -= 1
89
- end
90
-
91
- def run_on_db_status
92
- Thread.current[:run_on_db_status] ||= {:count => 0, :go_slave => false}
93
- end
94
-
95
- def go_slave?(options)
96
- !FreshConnection::SlaveConnection.ignore_model?(self.name) && connection.open_transactions == 0 &&
97
- (!options.is_a?(Hash) || !options.key?(:readonly) || options[:readonly].nil? || options[:readonly])
98
- end
99
-
100
- def run_on_readonly_db
101
- FreshConnection::SlaveConnection.slave_access_in
102
- yield
103
- ensure
104
- FreshConnection::SlaveConnection.slave_access_out
105
- end
106
- end
107
- end
108
- end
109
-