ebisu_connection 1.0.0 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6ca70a47990e4d8b4785fd2d744777cce70ca488
4
- data.tar.gz: deb891cf866a57e0fa9945215737bbe73774469e
3
+ metadata.gz: 764c768519c8100f8cebb21c2f82a2f7366b9027
4
+ data.tar.gz: fe2a33cd780b591989c14007ec9fd37fd14f8702
5
5
  SHA512:
6
- metadata.gz: 073399cd8859740d5a14c69b4932f4615438841012adae7f4bd95f909c7f62754dca313e9ccd958d3863c6932b16cf5142adfb7a75a0d95ebfb27aeddd0fe425
7
- data.tar.gz: 8656575ecfac9e40ef0b9b56a5ae34f836e174467c84524ae5e617b48fab1cf200308a72bb8de5573f6a76a2a45920852ec401904daf10b163467250afca86b7
6
+ metadata.gz: be9cbf840dbeca58b62dae564ccd7108e03d8140c9a359e2a0c75ab52ae8a0406f20cbef725fc8fcef0d818fa85d3270883621955584e7552abb0e5739ed09f7
7
+ data.tar.gz: 4ef3c1940b977e53318ea19cef4c27b5ba80fa8d20377d8aecbd319fd5bf75387a9de8c3cb3893f09b4a338d17ce8afd3a512098d113f89911c7db54d418697b
data/.travis.yml CHANGED
@@ -1,11 +1,15 @@
1
1
  language: ruby
2
2
  before_install:
3
3
  - gem install bundler
4
+ services:
5
+ - mysql
6
+ - postgresql
4
7
  before_script:
5
- - mysql -e 'create database ebisu_connection_test;'
6
- - mysql -e 'create database ebisu_connection_test_master;'
7
- - mysql -e 'create database ebisu_connection_test_slave;'
8
8
  - bundle update
9
+ - cp test/config/database_postgresql.yml.travis test/config/database_postgresql.yml
10
+ - psql -c 'create database fresh_connection_test_master;' -U postgres
11
+ - psql -c 'create database fresh_connection_test_slave1;' -U postgres
12
+ - psql -c 'create database fresh_connection_test_slave2;' -U postgres
9
13
  cache: bundler
10
14
  rvm:
11
15
  - 2.0.0
@@ -14,10 +18,25 @@ rvm:
14
18
  - 2.3.0
15
19
  - ruby-head
16
20
  gemfile:
17
- - gemfiles/rails3.gemfile
18
21
  - gemfiles/rails40.gemfile
19
22
  - gemfiles/rails41.gemfile
20
23
  - gemfiles/rails42.gemfile
24
+ - gemfiles/rails50.gemfile
25
+ matrix:
26
+ exclude:
27
+ - rvm: 2.3.0
28
+ gemfile: gemfiles/rails40.gemfile
29
+ - rvm: ruby-head
30
+ gemfile: gemfiles/rails40.gemfile
31
+ - rvm: 2.0.0
32
+ gemfile: gemfiles/rails50.gemfile
33
+ - rvm: 2.1.8
34
+ gemfile: gemfiles/rails50.gemfile
35
+ allow_failures:
36
+ - rvm: ruby-head
37
+ - gemfile: gemfiles/rails50.gemfile
38
+ fast_finish: true
21
39
  notifications:
22
40
  emails:
23
41
  - tsukasa.oishi@gmail.com
42
+ bundler_args: --jobs 3 --retry 3
data/Appraisals CHANGED
@@ -1,15 +1,19 @@
1
- appraise "rails3" do
2
- gem "activerecord", "~> 3.2.0"
3
- end
4
-
5
1
  appraise "rails40" do
6
2
  gem "activerecord", "~> 4.0.0"
3
+ gem 'mysql2', '~> 0.3.10'
7
4
  end
8
5
 
9
6
  appraise "rails41" do
10
7
  gem "activerecord", "~> 4.1.0"
8
+ gem 'mysql2', '~> 0.3.13'
11
9
  end
12
10
 
13
11
  appraise "rails42" do
14
12
  gem "activerecord", "~> 4.2.0"
13
+ gem 'mysql2', '~> 0.3.13'
14
+ end
15
+
16
+ appraise "rails50" do
17
+ gem "activerecord", "5.0.0.beta3"
18
+ gem 'mysql2', '>= 0.3.18', '< 0.5'
15
19
  end
data/README.md CHANGED
@@ -1,10 +1,60 @@
1
1
  # EbisuConnection
2
-
3
2
  [![Gem Version](https://badge.fury.io/rb/ebisu_connection.svg)](http://badge.fury.io/rb/ebisu_connection) [![Build Status](https://travis-ci.org/tsukasaoishi/ebisu_connection.svg?branch=master)](https://travis-ci.org/tsukasaoishi/ebisu_connection) [![Code Climate](https://codeclimate.com/github/tsukasaoishi/ebisu_connection/badges/gpa.svg)](https://codeclimate.com/github/tsukasaoishi/ebisu_connection)
4
3
 
5
- EbisuConnection supports to connect with Mysql slave servers. It doesn't need Load Balancer.
6
- You can assign a performance weight to each slave server. And slave config is reflected dynamic.
7
- EbisuConnection uses FreshConnection (https://github.com/tsukasaoishi/fresh_connection).
4
+ EbisuConnection allows access to slave servers.
5
+ You could assign a performance weight to each slave server.
6
+
7
+ ```
8
+ Rails ------------ Master DB
9
+ |
10
+ |
11
+ +---- Slave1 DB (weight 10)
12
+ |
13
+ |
14
+ +---- Slave2 DB (weight 20)
15
+ ```
16
+
17
+ If you could put a load balancer in front of slave servers, should use [FreshConnection](https://github.com/tsukasaoishi/fresh_connection).
18
+
19
+ ## Usage
20
+ ### Access to Slave
21
+ Read query goes to the slave server.
22
+
23
+ ```ruby
24
+ Article.where(:id => 1)
25
+ ```
26
+
27
+ ### Access to Master
28
+ If read query want to access to the master server, use `read_master`.
29
+ In before version 0.3.1, can use `readonly(false)`.
30
+
31
+ ```ruby
32
+ Article.where(:id => 1).read_master
33
+ ```
34
+
35
+ In transaction, All queries go to the master server.
36
+
37
+ ```ruby
38
+ Article.transaction do
39
+ Article.where(:id => 1)
40
+ end
41
+ ```
42
+
43
+ Create, Update and Delete queries go to the master server.
44
+
45
+ ```ruby
46
+ article = Article.create(...)
47
+ article.title = "FreshConnection"
48
+ article.save
49
+ article.destory
50
+ ```
51
+
52
+ ## Support Rails version
53
+ EbisuConnection supports Rails version 4.0 or later.
54
+ If you are using Rails 3.2, could use EbisuConnection version 1.0.0 or before.
55
+
56
+ ## Support DB
57
+ EbisuConnection supports MySQL and PostgreSQL.
8
58
 
9
59
  ## Installation
10
60
 
@@ -48,10 +98,10 @@ production:
48
98
  host: slave
49
99
  ```
50
100
 
51
- ```slave``` is base config to connect to slave servers.
52
- Others will use the master setting. If you want to change, write in the slave.
53
-
54
- Config of each slave server fill out config/slave.yaml
101
+ ```slave``` is a config to connect to slave servers.
102
+ Others will use the master server settings.
103
+
104
+ Config of each slave server fill out to `config/slave.yml`
55
105
 
56
106
  ```yaml
57
107
  production:
@@ -62,7 +112,7 @@ production:
62
112
  weight: 30
63
113
  ```
64
114
 
65
- config/slave.yaml is checked by end of action. If config changed, it's reflected dynamic. Application doesn't need restart.
115
+ If ``config/slave.yml`` changed, it is reflected dynamic. Application doesn't need restart.
66
116
 
67
117
  ```yaml
68
118
  "hostname, weight"
@@ -96,7 +146,7 @@ production:
96
146
  host: admin_slaves
97
147
  ```
98
148
 
99
- Config of each slave server fill out config/slave.yaml
149
+ Config of each slave server fill out to `config/slave.yml`
100
150
 
101
151
  ```yaml
102
152
  production:
@@ -111,7 +161,6 @@ production:
111
161
  - "slave4, 20"
112
162
  ```
113
163
 
114
-
115
164
  And call establish_fresh_connection method in model that access to ```admin_slave``` slave group.
116
165
 
117
166
  ```ruby
@@ -148,32 +197,6 @@ end
148
197
  If model that always access to master servers is exist, You may want to write ```master_db_only!``` in model.
149
198
  The model that master_db_only model's child is always access to master db.
150
199
 
151
- ## Usage
152
-
153
- Read query will be access to slave server.
154
-
155
- ```ruby
156
- Article.where(:id => 1)
157
- Article.count
158
- ```
159
-
160
- If you want to access to the master server, use read_master.
161
-
162
- ```ruby
163
- Article.where(:id => 1).read_master
164
- ```
165
-
166
- It is possible to use readonly(false) instead of read_master, but it will be depricated at future version.
167
-
168
- In transaction, Always will be access to master server.
169
-
170
- ```ruby
171
- Article.transaction do
172
- Article.where(:id => 1)
173
- end
174
- ```
175
-
176
-
177
200
  ### for Unicorn
178
201
 
179
202
  ```ruby
@@ -205,13 +228,12 @@ To run the test suite, you need mysql installed.
205
228
  How to setup your test environment.
206
229
 
207
230
  ```bash
208
- bundle install --path .bundle
209
- bundle exec appraisal install
231
+ ./bin/setup
210
232
  ```
211
233
 
212
234
  This command run the spec suite for all rails versions supported.
213
235
 
214
236
  ```base
215
- bundle exec appraisal rake test
237
+ ./bin/test
216
238
  ```
217
239
 
data/Rakefile CHANGED
@@ -1,10 +1,22 @@
1
1
  require "bundler/gem_tasks"
2
2
  require 'rake/testtask'
3
3
 
4
- Rake::TestTask.new do |t|
5
- t.libs.push "test"
6
- t.test_files = FileList['test/**/*_test.rb']
7
- t.verbose = true
4
+ desc 'Run mysql2 and postgresql test'
5
+ task :test do
6
+ Rake::Task["test:mysql2"].invoke
7
+ Rake::Task["test:postgresql"].invoke
8
+ end
9
+
10
+ namespace :test do
11
+ %w(mysql2 postgresql).each do |db|
12
+ Rake::TestTask.new(db) do |t|
13
+ t.libs << "test"
14
+ t.libs << "lib"
15
+ t.test_files = FileList["test/config/prepare_#{db}", 'test/**/*_test.rb']
16
+ t.verbose = false
17
+ t.warning = false
18
+ end
19
+ end
8
20
  end
9
21
 
10
22
  task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ebisu_connection"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install --path .bundle
7
+ bundle exec appraisal install
8
+
9
+ # Do any other automated setup that you need to do here
data/bin/test ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle exec appraisal rake test
@@ -21,8 +21,11 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.required_ruby_version = '>= 2.0'
23
23
 
24
- spec.add_dependency 'fresh_connection', '~> 1.0.0'
24
+ spec.add_dependency 'fresh_connection', '~> 2.0.0'
25
+ spec.add_dependency 'concurrent-ruby', '~> 1.0.0'
25
26
 
27
+ spec.add_development_dependency 'mysql2', '>= 0.3.13', '< 0.5'
28
+ spec.add_development_dependency 'pg', '~> 0.11'
26
29
  spec.add_development_dependency "bundler", ">= 1.3.0", "< 2.0"
27
30
  spec.add_development_dependency "rake", ">= 0.8.7"
28
31
  spec.add_development_dependency 'appraisal'
@@ -3,5 +3,6 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "activerecord", "~> 4.0.0"
6
+ gem "mysql2", "~> 0.3.10"
6
7
 
7
8
  gemspec :path => "../"
@@ -3,5 +3,6 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "activerecord", "~> 4.1.0"
6
+ gem "mysql2", "~> 0.3.13"
6
7
 
7
8
  gemspec :path => "../"
@@ -3,5 +3,6 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "activerecord", "~> 4.2.0"
6
+ gem "mysql2", "~> 0.3.13"
6
7
 
7
8
  gemspec :path => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "5.0.0.beta3"
6
+ gem "mysql2", ">= 0.3.18", "< 0.5"
7
+
8
+ gemspec :path => "../"
@@ -27,7 +27,10 @@ module EbisuConnection
27
27
  def slaves_file
28
28
  return @slaves_file if @slaves_file
29
29
  raise "nothing slaves_file. You have to set a file path using EbisuConnection.slaves_file= method" unless defined?(Rails)
30
- File.join(Rails.root, "config/slave.yaml")
30
+
31
+ @slaves_file = %w(yml yaml).map{|ext| Rails.root.join("config/slave.#{ext}").to_s }.detect {|f| File.exist?(f) }
32
+ raise "nothing slaves_file. You have to put a config/slave.yml file" unless @slaves_file
33
+ @slaves_file
31
34
  end
32
35
 
33
36
  def check_interval
@@ -1,13 +1,10 @@
1
- require 'fresh_connection/abstract_connection_manager'
2
- require 'ebisu_connection/conf_file'
3
- require 'ebisu_connection/slave_group'
4
- require 'active_support/deprecation'
1
+ require 'concurrent'
5
2
 
6
3
  module EbisuConnection
7
4
  class ConnectionManager < FreshConnection::AbstractConnectionManager
8
5
  def initialize(slave_group = "slave")
9
6
  super
10
- @slaves = {}
7
+ @slaves = Concurrent::Map.new
11
8
  end
12
9
 
13
10
  def slave_connection
@@ -23,59 +20,43 @@ module EbisuConnection
23
20
  end
24
21
  end
25
22
 
26
- def recovery(failure_connection, exception)
27
- if slave_down_message?(exception.message)
28
- slaves.remove_connection(failure_connection)
29
- true
30
- else
31
- false
32
- end
33
- end
34
-
35
23
  def clear_all_connections!
36
- synchronize do
37
- @slaves.values.each do |s|
38
- s.all_disconnect!
39
- end
40
-
41
- @slaves = {}
42
- ConfFile.conf_clear!
24
+ @slaves.each_value do |s|
25
+ s.all_disconnect!
43
26
  end
27
+
28
+ @slaves.clear
29
+ ConfFile.conf_clear!
44
30
  end
45
31
 
46
- def clear_all_connection!
47
- ActiveSupport::Deprecation.warn("clear_all_connection! has been deprecated. Use clear_all_connections! instead", caller)
48
- clear_all_connections!
32
+ def recovery?
33
+ slaves.recovery_connection?
49
34
  end
50
35
 
51
36
  private
52
37
 
53
38
  def check_own_connection
54
- synchronize do
55
- s = @slaves[current_thread_id]
39
+ s = @slaves[current_thread_id]
56
40
 
57
- if s && s.reserved_release?
58
- s.all_disconnect!
59
- @slaves.delete(current_thread_id)
60
- true
61
- else
62
- false
63
- end
41
+ if s && s.reserved_release?
42
+ s.all_disconnect!
43
+ @slaves.delete(current_thread_id)
44
+ true
45
+ else
46
+ false
64
47
  end
65
48
  end
66
49
 
67
50
  def reserve_release_all_connection
68
- synchronize do
69
- @slaves.values.each do |s|
70
- s.reserve_release_connection!
71
- end
72
- ConfFile.conf_clear!
51
+ @slaves.each_value do |s|
52
+ s.reserve_release_connection!
73
53
  end
54
+ ConfFile.conf_clear!
74
55
  end
75
56
 
76
57
  def slaves
77
- synchronize do
78
- @slaves[current_thread_id] ||= get_slaves
58
+ @slaves.fetch_or_store(current_thread_id) do |_|
59
+ get_slaves
79
60
  end
80
61
  end
81
62
 
@@ -86,5 +67,9 @@ module EbisuConnection
86
67
  def slaves_conf
87
68
  ConfFile.slaves_conf(slave_group)
88
69
  end
70
+
71
+ def current_thread_id
72
+ Thread.current.object_id
73
+ end
89
74
  end
90
75
  end
@@ -24,6 +24,10 @@ module EbisuConnection
24
24
  @connection ||= @connection_factory.new_connection
25
25
  end
26
26
 
27
+ def active?
28
+ connection.active?
29
+ end
30
+
27
31
  def disconnect!
28
32
  if @connection
29
33
  @connection.disconnect!
@@ -1,6 +1,3 @@
1
- require 'ebisu_connection/greatest_common_divisor'
2
- require 'ebisu_connection/slave'
3
-
4
1
  module EbisuConnection
5
2
  class SlaveGroup
6
3
  class AllSlavesHasGoneError < StandardError; end
@@ -18,13 +15,19 @@ module EbisuConnection
18
15
  @slaves[@roulette.sample]
19
16
  end
20
17
 
21
- def remove_connection(connection)
22
- return unless s = @slaves.detect{|s| s.connection == connection}
23
- s.disconnect! rescue nil
24
- @slaves.delete(s)
18
+ def recovery_connection?
19
+ dead_slaves = @slaves.select{|s| !s.active? }
20
+ return false if dead_slaves.empty?
21
+
22
+ dead_slaves.each do |s|
23
+ s.disconnect!
24
+ @slaves.delete(s)
25
+ end
26
+
25
27
  raise AllSlavesHasGoneError if @slaves.empty?
28
+
26
29
  recalc_roulette
27
- nil
30
+ true
28
31
  end
29
32
 
30
33
  def all_disconnect!
@@ -1,3 +1,3 @@
1
1
  module EbisuConnection
2
- VERSION = "1.0.0"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -1,8 +1,12 @@
1
1
  require "fresh_connection"
2
- require 'ebisu_connection/conf_file'
3
- require 'ebisu_connection/connection_manager'
4
2
 
5
3
  module EbisuConnection
4
+ autoload :ConfFile, 'ebisu_connection/conf_file'
5
+ autoload :ConnectionManager, 'ebisu_connection/connection_manager'
6
+ autoload :SlaveGroup, 'ebisu_connection/slave_group'
7
+ autoload :Slave, 'ebisu_connection/slave'
8
+ autoload :GreatestCommonDivisor, 'ebisu_connection/greatest_common_divisor'
9
+
6
10
  class << self
7
11
  attr_writer :env
8
12
 
metadata CHANGED
@@ -1,17 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ebisu_connection
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tsukasaoishi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-01-10 00:00:00.000000000 Z
11
+ date: 2016-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fresh_connection
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: concurrent-ruby
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - "~>"
@@ -24,6 +38,40 @@ dependencies:
24
38
  - - "~>"
25
39
  - !ruby/object:Gem::Version
26
40
  version: 1.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: mysql2
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.3.13
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '0.5'
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 0.3.13
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.5'
61
+ - !ruby/object:Gem::Dependency
62
+ name: pg
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '0.11'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '0.11'
27
75
  - !ruby/object:Gem::Dependency
28
76
  name: bundler
29
77
  requirement: !ruby/object:Gem::Requirement
@@ -116,11 +164,15 @@ files:
116
164
  - LICENSE.txt
117
165
  - README.md
118
166
  - Rakefile
167
+ - bin/console
168
+ - bin/setup
169
+ - bin/test
119
170
  - ebisu_connection.gemspec
120
171
  - gemfiles/rails3.gemfile
121
172
  - gemfiles/rails40.gemfile
122
173
  - gemfiles/rails41.gemfile
123
174
  - gemfiles/rails42.gemfile
175
+ - gemfiles/rails50.gemfile
124
176
  - lib/ebisu_connection.rb
125
177
  - lib/ebisu_connection/conf_file.rb
126
178
  - lib/ebisu_connection/connection_manager.rb