fresh_connection 0.0.7 → 0.1.0

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.
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
-