ebisu_connection 0.0.1
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 +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +91 -0
- data/Rakefile +1 -0
- data/ebisu_connection.gemspec +26 -0
- data/lib/ebisu_connection.rb +6 -0
- data/lib/ebisu_connection/connection_manager.rb +86 -0
- data/lib/ebisu_connection/slaves.rb +95 -0
- data/lib/ebisu_connection/version.rb +3 -0
- metadata +111 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b135ecfde83d564cc7dcfbfaa7632f057fdf2fe1
|
4
|
+
data.tar.gz: 39f3cdb331514ae4ea8d24d9e463f7287bd60dd9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c59b5f27c126da53ff6a29e8f7604d69be14c0f0d55347ea01d20d0efad05a428765f21dfdfc160265167b26e7ad28135f118c875ae226bd9453c2cd721b0d1d
|
7
|
+
data.tar.gz: f6ffaf1813892a30f3750d0a796170b36a0fc8e162644d436dcbc8e3640abd532dadf39786de1bec1206884e5190a08fd4c7317ece15643683110cfec28a447c
|
data/.gitignore
ADDED
data/Gemfile
ADDED
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,91 @@
|
|
1
|
+
# EbisuConnection
|
2
|
+
|
3
|
+
EbisuConnection supports to connect with Mysql slave servers. It doesn't need Load Balancer.
|
4
|
+
You can assign a performance weight to each slave server. And slave config is reflected dynamic.
|
5
|
+
EbisuConnection uses FreshConnection (https://github.com/tsukasaoishi/fresh_connection).
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
EbisuConnection has tested Rails3.2.16 and Rails4.0.2.
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'ebisu_connection'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install ebisu_connection
|
22
|
+
|
23
|
+
## Config
|
24
|
+
|
25
|
+
config/database.yml
|
26
|
+
|
27
|
+
production:
|
28
|
+
adapter: mysql2
|
29
|
+
encoding: utf8
|
30
|
+
reconnect: true
|
31
|
+
database: kaeru
|
32
|
+
pool: 5
|
33
|
+
username: master
|
34
|
+
password: master
|
35
|
+
host: localhost
|
36
|
+
socket: /var/run/mysqld/mysqld.sock
|
37
|
+
|
38
|
+
slave:
|
39
|
+
username: slave
|
40
|
+
password: slave
|
41
|
+
host: slave
|
42
|
+
|
43
|
+
slave is base config to connect to slave servers.
|
44
|
+
Others will use the master setting. If you want to change, write in the slave.
|
45
|
+
|
46
|
+
Config of each slave server fill out config/slave.yaml
|
47
|
+
|
48
|
+
- "slave1, 10"
|
49
|
+
- "slave2, 20"
|
50
|
+
-
|
51
|
+
host: "slave3"
|
52
|
+
weight: 30
|
53
|
+
|
54
|
+
config/slave.yaml is checked by end of action. If config changed, it's reflected dynamic. Application doesn't need restart.
|
55
|
+
|
56
|
+
"hostname, weight"
|
57
|
+
|
58
|
+
String format is it. You can write config with hash.
|
59
|
+
|
60
|
+
### Only master models
|
61
|
+
|
62
|
+
config/initializers/fresh_connection.rb
|
63
|
+
|
64
|
+
FreshConnection::SlaveConnection.ignore_models = %w|Model1 Model2|
|
65
|
+
|
66
|
+
If models that ignore access to slave servers is exist, You can write model name at FreshConnection::SlaveConnection.ignore models.
|
67
|
+
|
68
|
+
## Usage
|
69
|
+
|
70
|
+
Read query will be access to slave server.
|
71
|
+
|
72
|
+
Article.where(:id => 1)
|
73
|
+
|
74
|
+
If you want to access to master saver, use readonly(false).
|
75
|
+
|
76
|
+
Article.where(:id => 1).readonly(false)
|
77
|
+
|
78
|
+
In transaction, Always will be access to master server.
|
79
|
+
|
80
|
+
Article.transaction do
|
81
|
+
Article.where(:id => 1)
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
## Contributing
|
86
|
+
|
87
|
+
1. Fork it
|
88
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
89
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
90
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
91
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ebisu_connection/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ebisu_connection"
|
8
|
+
spec.version = EbisuConnection::VERSION
|
9
|
+
spec.authors = ["tsukasaoishi"]
|
10
|
+
spec.email = ["tsukasa.oishi@gmail.com"]
|
11
|
+
spec.description = %q{EbisuConnection supports to connect with Mysql slave servers. It doesn't need Load Balancer.}
|
12
|
+
spec.summary = %q{EbisuConnection supports to connect with Mysql slave servers.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
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
|
+
spec.add_dependency 'fresh_connection', '>= 0.1.2'
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module EbisuConnection
|
4
|
+
class ConnectionManager
|
5
|
+
CHECK_INTERVAL = 1.minute
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_writer :slaves_file
|
9
|
+
attr_accessor :slave_type
|
10
|
+
|
11
|
+
def slaves_file
|
12
|
+
@slaves_file || File.join(Rails.root, "config/slave.yaml")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@mutex = Mutex.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def slave_connection
|
21
|
+
slaves.sample.connection
|
22
|
+
end
|
23
|
+
|
24
|
+
def put_aside!
|
25
|
+
return unless @file_mtime
|
26
|
+
|
27
|
+
now = Time.now
|
28
|
+
@check_time ||= now
|
29
|
+
return if now - @check_time < CHECK_INTERVAL
|
30
|
+
@check_time = now
|
31
|
+
|
32
|
+
mtime = File.mtime(self.class.slaves_file)
|
33
|
+
return if @file_mtime == mtime
|
34
|
+
|
35
|
+
clear_all_connection!
|
36
|
+
end
|
37
|
+
|
38
|
+
def clear_all_connection!
|
39
|
+
@mutex.synchronize do
|
40
|
+
@slaves.values.each do |s|
|
41
|
+
s.all_disconnect!
|
42
|
+
end
|
43
|
+
|
44
|
+
@slaves = nil
|
45
|
+
@slave_conf = nil
|
46
|
+
@spec = nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def slaves
|
53
|
+
@mutex.synchronize do
|
54
|
+
@slaves ||= {}
|
55
|
+
@slaves[current_thread_id] ||= get_slaves
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_slaves
|
60
|
+
EbisuConnection::Slaves.new(slaves_conf, spec)
|
61
|
+
end
|
62
|
+
|
63
|
+
def slaves_conf
|
64
|
+
@slaves_conf ||= get_slaves_conf
|
65
|
+
end
|
66
|
+
|
67
|
+
def spec
|
68
|
+
@spec ||= get_spec
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_slaves_conf
|
72
|
+
@file_mtime = File.mtime(self.class.slaves_file)
|
73
|
+
conf = YAML.load_file(self.class.slaves_file)
|
74
|
+
self.class.slave_type ? conf[self.class.slave_type] : conf
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_spec
|
78
|
+
ret = ActiveRecord::Base.configurations[Rails.env]
|
79
|
+
ret.merge(ret["slave"] || {})
|
80
|
+
end
|
81
|
+
|
82
|
+
def current_thread_id
|
83
|
+
Thread.current.object_id
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module EbisuConnection
|
2
|
+
class Slaves
|
3
|
+
class Slave
|
4
|
+
attr_reader :hostname, :weight
|
5
|
+
|
6
|
+
def initialize(conf, spec)
|
7
|
+
case conf
|
8
|
+
when String
|
9
|
+
@hostname, weight = conf.split(/\s*,\s*/)
|
10
|
+
edit_spec = {:host => @hostname}
|
11
|
+
when Hash
|
12
|
+
conf = symbolize_keys(conf)
|
13
|
+
weight = conf.delete(:weight)
|
14
|
+
edit_spec = conf
|
15
|
+
@hostname = conf[:host]
|
16
|
+
else
|
17
|
+
raise ArgumentError, "slaves config is invalid"
|
18
|
+
end
|
19
|
+
|
20
|
+
@spec = spec.merge(edit_spec)
|
21
|
+
@weight = (weight || 1).to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
def connection
|
25
|
+
@connection ||= ActiveRecord::Base.send("#{@spec["adapter"]}_connection", @spec)
|
26
|
+
end
|
27
|
+
|
28
|
+
def disconnect!
|
29
|
+
if @connection
|
30
|
+
@connection.disconnect!
|
31
|
+
@connection = nil
|
32
|
+
end
|
33
|
+
rescue
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def symbolize_keys(hash)
|
39
|
+
symbolize_hash = {}
|
40
|
+
hash.each do |k,v|
|
41
|
+
symbolize_hash[k.to_sym] = v
|
42
|
+
end
|
43
|
+
symbolize_hash
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize(slaves_conf, spec)
|
48
|
+
weight_list = []
|
49
|
+
@slaves = slaves_conf.map do |conf|
|
50
|
+
s = Slave.new(conf, spec)
|
51
|
+
weight_list << s.weight
|
52
|
+
s
|
53
|
+
end
|
54
|
+
|
55
|
+
@roulette = []
|
56
|
+
gcd = get_gcd(weight_list)
|
57
|
+
weight_list.each_with_index do |w, index|
|
58
|
+
weight = w / gcd
|
59
|
+
@roulette.concat([index] * weight)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def sample
|
64
|
+
@slaves[@roulette.sample]
|
65
|
+
end
|
66
|
+
|
67
|
+
def all_disconnect!
|
68
|
+
@slaves.each {|s| s.disconnect!}
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def get_gcd(list)
|
74
|
+
list = list.sort.uniq
|
75
|
+
n = list.shift
|
76
|
+
return n if n == 1 || list.empty?
|
77
|
+
|
78
|
+
while !list.empty?
|
79
|
+
m = list.shift
|
80
|
+
n = gcd_euclid(m, n)
|
81
|
+
end
|
82
|
+
n
|
83
|
+
end
|
84
|
+
|
85
|
+
def gcd_euclid(m, n)
|
86
|
+
m, n = n, m if m < n
|
87
|
+
while n != 0
|
88
|
+
work = m % n
|
89
|
+
m = n
|
90
|
+
n = work
|
91
|
+
end
|
92
|
+
m
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ebisu_connection
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- tsukasaoishi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-12-12 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: fresh_connection
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.1.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.1.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: EbisuConnection supports to connect with Mysql slave servers. It doesn't
|
70
|
+
need Load Balancer.
|
71
|
+
email:
|
72
|
+
- tsukasa.oishi@gmail.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- ebisu_connection.gemspec
|
83
|
+
- lib/ebisu_connection.rb
|
84
|
+
- lib/ebisu_connection/connection_manager.rb
|
85
|
+
- lib/ebisu_connection/slaves.rb
|
86
|
+
- lib/ebisu_connection/version.rb
|
87
|
+
homepage: ''
|
88
|
+
licenses:
|
89
|
+
- MIT
|
90
|
+
metadata: {}
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 2.0.0
|
108
|
+
signing_key:
|
109
|
+
specification_version: 4
|
110
|
+
summary: EbisuConnection supports to connect with Mysql slave servers.
|
111
|
+
test_files: []
|