ar_mysql_flexmaster 0.4.4 → 0.5.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: dffa59e91370055f41c5d4e7d6f6d2d0995251a6
4
+ data.tar.gz: afcf28a678aa561fcf57d9cbe1fd63038e3385ae
5
+ SHA512:
6
+ metadata.gz: 8123f48cb4a821997e488027544405776fb2dfc3aff20ae99b2f5018ea70f02e079a71f4b6328c2dc5351e9f1bd3715e1ec6694cf14ed65f2af3d456bb685086
7
+ data.tar.gz: f45fe4dbb857085b4bd5d0adbfdd778b52a625b22669def9812561505b08d6f64f7ee6d50cb06f65860689da7c58d6c9537aa1d50cc30c94021d0c0d2eb1f474
data/.travis.yml CHANGED
@@ -1,13 +1,31 @@
1
+ language: ruby
2
+
1
3
  rvm:
2
4
  - 1.9.3
3
5
  - 2.0
6
+ - 2.1
7
+
4
8
  gemfile:
5
- - gemfiles/rails2.gemfile
6
- - gemfiles/rails3.gemfile
9
+ - gemfiles/rails2.3.gemfile
10
+ - gemfiles/rails3.0.gemfile
7
11
  - gemfiles/rails3.2.gemfile
12
+ - gemfiles/rails4.0.gemfile
13
+ - gemfiles/rails4.1.gemfile
14
+ - gemfiles/rails4.2.gemfile
15
+
16
+ sudo: false
17
+
18
+ bundler_args: --no-deployment
19
+
20
+ script: bundle exec rake test
21
+
8
22
  matrix:
9
23
  exclude:
10
24
  - rvm: 2.0
11
- gemfile: gemfiles/rails2.gemfile
25
+ gemfile: gemfiles/rails2.3.gemfile
12
26
  - rvm: 2.0
13
- gemfile: gemfiles/rails3.gemfile
27
+ gemfile: gemfiles/rails3.0.gemfile
28
+ - rvm: 2.1
29
+ gemfile: gemfiles/rails2.3.gemfile
30
+ - rvm: 2.1
31
+ gemfile: gemfiles/rails3.0.gemfile
data/Gemfile CHANGED
@@ -1,6 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in ar_mysql_flexmaster.gemspec
4
3
  gemspec
5
- gem "debugger", "~>1.5.0"
6
- gem "appraisal"
4
+
5
+ gem "rake"
data/README.md CHANGED
@@ -1,26 +1,18 @@
1
- # ArMysqlFlexmaster
1
+ [![Build Status](https://travis-ci.org/osheroff/ar_mysql_flexmaster.svg?branch=master)](https://travis-ci.org/osheroff/ar_mysql_flexmaster)
2
2
 
3
- Mysql Flexmaster is an adapter for ActiveRecord that allows an application node to choose
4
- among a list of potential masters at runtime. It trades some properties of a more traditional
5
- HA solution (load balancing, middleware) for simplicity of operation.
6
-
7
- ## Installation
8
-
9
- Add this line to your application's Gemfile:
10
-
11
- gem 'ar_mysql_flexmaster'
12
-
13
- And then execute:
3
+ # Flexmaster
14
4
 
15
- $ bundle
16
-
17
- Or install it yourself as:
18
-
19
- $ gem install ar_mysql_flexmaster
5
+ Flexmaster is an adapter for ActiveRecord and mysql that allows an application node to find a master
6
+ among a list of potential masters at runtime. It trades some properties of a more traditional
7
+ HA solution (load balancing, middleware) for simplicity of operation.
20
8
 
21
9
  ## Configuration:
22
10
 
23
- database.yml contains a list of hosts -- all of them potential masters, all of them potential replicas.
11
+ Your environment should be configured with 1 active master and N replicas. Each replica should have mysql's
12
+ global "READ_ONLY" flag set to true (this is really best practices for your replicas anyway, but flexmaster
13
+ depends on it).
14
+
15
+ database.yml should contain a list of hosts -- all of them potential masters, all of them potential replicas.
24
16
  It should look like this:
25
17
 
26
18
  ```
@@ -36,6 +28,8 @@ production_slave:
36
28
  hosts: ["db01:3306", "db02:3306"]
37
29
  ```
38
30
 
31
+ In this example, we've configured two diferent connections for rails to use. Note that they're identicle except for the `slave:true` key in the production_slave yaml block.
32
+ Adding `slave:true` indicates to flexmaster that this connection should prefer a read-only slave wherever possible.
39
33
 
40
34
  ## How it works
41
35
 
@@ -53,19 +47,22 @@ it finds the correct host.
53
47
  For master configurations (slave: true is not specified):
54
48
 
55
49
  The application will probe each host in turn, and find the mysql candidate among these nodes
56
- that is read-write (SET GLOBAL READ_ONLY=0). If it finds more than one node where READ_ONLY == 0, it will
57
- abort.
50
+ that is read-write (SET GLOBAL READ\_ONLY=0).
51
+
52
+ If it finds more than one node where READ_ONLY == 0, it will abort.
58
53
 
59
54
  For slave configurations (slave: true specified):
60
55
 
61
- The application will choose a replica at random from amongst those where READ_ONLY == 1.
56
+ The application will choose a replica at random from amongst those where READ_ONLY == 1. If no active replicas are found,
57
+ it will fall back to the master.
62
58
 
63
59
  ### run time
64
60
 
65
- Before each transaction is begun on the master, the application checks the status of the READ_ONLY variable.
66
- If READ_ONLY == 0, it will proceed with the transaction as normal. If READ_ONLY == 1, it will drop the current
67
- connection and re-poll the cluster for the current master, sleeping up to a default of 5 seconds to wait for
68
- the new master to be promoted. When it finds the new master, it will begin the transaction there.
61
+ Before each transaction is opened on the master, the application checks the status of the READ_ONLY variable.
62
+ If READ\_ONLY == 0 (our active connection is still to the current master), it will proceed with the
63
+ transaction as normal. If READ\_ONLY == 1 (the master has been demoted), it will drop the current connection
64
+ and re-poll the cluster, sleeping for up to a default of 5 seconds for
65
+ a new master to be promoted. When it finds the new master, it will continue playing the transaction on it.
69
66
 
70
67
  ### promoting a new master
71
68
 
@@ -76,7 +73,7 @@ The process of promoting a new master to head the cluster should be as follows:
76
73
  1. identify a new candidate master
77
74
  1. ensure that all other replicas in the cluster are chained off the candidate master; you want the
78
75
  chain to look like this:
79
-
76
+
80
77
  ```
81
78
  <existing master> -> <candidate master> -> <other replicas>
82
79
  -> <other replicas>
@@ -84,13 +81,13 @@ The process of promoting a new master to head the cluster should be as follows:
84
81
  ```
85
82
 
86
83
  1. set the old master to READ_ONLY = 1
87
- 1. record the master-bin-log position of the candidate master (if you want to re-use the old master)
84
+ 1. record the master-bin-log position of the candidate master (if you want to re-use the old master as a replica)
88
85
  1. set the new master to READ_ONLY = 0
89
86
 
90
- The application will eventually shift slave traffic to another node in the cluster, if available, and
91
- will drop their connection to the old master whenever a transaction is attempted, or after a certain
92
- number of queries.
87
+ The application nodes will, in time, find that the old master is inactive and will move their connections to the
88
+ new master.
93
89
 
90
+ The application will also eventually shift slave traffic to another node in the cluster.
94
91
 
95
92
  ### caveats, gotchas
96
93
 
@@ -98,6 +95,23 @@ number of queries.
98
95
  will crash. In theory there's a workaround for this problem, in pratice it's rather unwieldy due
99
96
  to a lack of shared global variables in mysql.
100
97
 
98
+ - Connection variables are unsupported, due to the connection being able to go away at any time.
99
+
100
+ ## Installation
101
+
102
+ Do a little dance. Drink a little water. Or:
103
+ Add this line to your application's Gemfile:
104
+
105
+ gem 'ar_mysql_flexmaster'
106
+
107
+ And then execute:
108
+
109
+ $ bundle
110
+
111
+ Or install it yourself as:
112
+
113
+ $ gem install ar_mysql_flexmaster
114
+
101
115
  ## Contributing
102
116
 
103
117
  1. Fork it
data/Rakefile CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env rake
2
2
  require 'rake/testtask'
3
3
 
4
- require 'appraisal'
5
4
  require 'bump/tasks'
5
+ require 'wwtd/tasks'
6
6
 
7
7
  Rake::TestTask.new(:test_units) do |test|
8
8
  test.libs << 'lib' << 'test'
@@ -10,10 +10,11 @@ Rake::TestTask.new(:test_units) do |test|
10
10
  test.verbose = true
11
11
  end
12
12
 
13
- task :test do
13
+ task :test do
14
14
  retval = true
15
15
  retval &= Rake::Task[:test_units].invoke
16
16
  retval &= system(File.dirname(__FILE__) + "/test/integration/run_integration_tests")
17
+ exit retval
17
18
  end
18
19
 
19
- task :default => :test
20
+ task :default => 'wwtd:local'
@@ -12,12 +12,13 @@ Gem::Specification.new do |gem|
12
12
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
13
13
  gem.name = "ar_mysql_flexmaster"
14
14
  gem.require_paths = ["lib"]
15
- gem.version = "0.4.4"
15
+ gem.version = "0.5.0"
16
16
 
17
17
  gem.add_runtime_dependency("mysql2")
18
18
  gem.add_runtime_dependency("activerecord")
19
19
  gem.add_runtime_dependency("activesupport")
20
- gem.add_development_dependency("appraisal")
20
+ gem.add_development_dependency("wwtd")
21
+ gem.add_development_dependency("minitest")
21
22
  gem.add_development_dependency("bump")
22
- gem.add_development_dependency("mysql_isolated_server", "~> 0.1.1")
23
+ gem.add_development_dependency("mysql_isolated_server", "~> 0.5")
23
24
  end
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec :path => "../"
4
+
5
+ gem "rake"
6
+ gem "rails", "~> 2.3.15"
7
+ gem "mysql2", "~> 0.2.0", "<= 0.2.18"
@@ -1,7 +1,7 @@
1
1
  PATH
2
- remote: /Users/ben/src/ar_mysql_flexmaster
2
+ remote: ../
3
3
  specs:
4
- ar_mysql_flexmaster (0.3.1)
4
+ ar_mysql_flexmaster (0.4.4)
5
5
  activerecord
6
6
  activesupport
7
7
  mysql2
@@ -19,18 +19,10 @@ GEM
19
19
  activeresource (2.3.18)
20
20
  activesupport (= 2.3.18)
21
21
  activesupport (2.3.18)
22
- appraisal (0.5.2)
23
- bundler
24
- rake
25
- columnize (0.3.6)
26
- debugger (1.5.0)
27
- columnize (>= 0.3.1)
28
- debugger-linecache (~> 1.2.0)
29
- debugger-ruby_core_source (~> 1.2.0)
30
- debugger-linecache (1.2.0)
31
- debugger-ruby_core_source (1.2.0)
22
+ bump (0.5.1)
23
+ minitest (5.4.3)
32
24
  mysql2 (0.2.18)
33
- mysql_isolated_server (0.1.1)
25
+ mysql_isolated_server (0.5.3)
34
26
  rack (1.1.6)
35
27
  rails (2.3.18)
36
28
  actionmailer (= 2.3.18)
@@ -39,17 +31,18 @@ GEM
39
31
  activeresource (= 2.3.18)
40
32
  activesupport (= 2.3.18)
41
33
  rake (>= 0.8.3)
42
- rake (10.0.4)
43
- yaggy (0.1.7)
34
+ rake (10.4.2)
35
+ wwtd (0.5.5)
44
36
 
45
37
  PLATFORMS
46
38
  ruby
47
39
 
48
40
  DEPENDENCIES
49
- appraisal
50
41
  ar_mysql_flexmaster!
51
- debugger (~> 1.5.0)
52
- mysql2 (~> 0.2.0)
53
- mysql_isolated_server (~> 0.1.1)
42
+ bump
43
+ minitest
44
+ mysql2 (~> 0.2.0, <= 0.2.18)
45
+ mysql_isolated_server (~> 0.5)
54
46
  rails (~> 2.3.15)
55
- yaggy
47
+ rake
48
+ wwtd
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec :path => "../"
4
+
5
+ gem "rake"
6
+ gem "rails", "~> 3.0.0"
7
+ gem "mysql2", "~> 0.2.0", "<= 0.2.18"
@@ -1,7 +1,7 @@
1
1
  PATH
2
- remote: /Users/ben/src/ar_mysql_flexmaster
2
+ remote: ../
3
3
  specs:
4
- ar_mysql_flexmaster (0.3.1)
4
+ ar_mysql_flexmaster (0.4.4)
5
5
  activerecord
6
6
  activesupport
7
7
  mysql2
@@ -36,31 +36,23 @@ GEM
36
36
  activemodel (= 3.0.20)
37
37
  activesupport (= 3.0.20)
38
38
  activesupport (3.0.20)
39
- appraisal (0.5.2)
40
- bundler
41
- rake
42
39
  arel (2.0.10)
43
40
  builder (2.1.2)
44
- columnize (0.3.6)
45
- debugger (1.5.0)
46
- columnize (>= 0.3.1)
47
- debugger-linecache (~> 1.2.0)
48
- debugger-ruby_core_source (~> 1.2.0)
49
- debugger-linecache (1.2.0)
50
- debugger-ruby_core_source (1.2.0)
41
+ bump (0.5.1)
51
42
  erubis (2.6.6)
52
43
  abstract (>= 1.0.0)
53
- i18n (0.5.0)
54
- json (1.7.7)
55
- mail (2.2.19)
44
+ i18n (0.5.4)
45
+ json (1.8.1)
46
+ mail (2.2.20)
56
47
  activesupport (>= 2.3.6)
57
48
  i18n (>= 0.4.0)
58
49
  mime-types (~> 1.16)
59
50
  treetop (~> 1.4.8)
60
- mime-types (1.23)
51
+ mime-types (1.25.1)
52
+ minitest (5.4.3)
61
53
  mysql2 (0.2.18)
62
- mysql_isolated_server (0.1.1)
63
- polyglot (0.3.3)
54
+ mysql_isolated_server (0.5.3)
55
+ polyglot (0.3.5)
64
56
  rack (1.2.8)
65
57
  rack-mount (0.6.14)
66
58
  rack (>= 1.0.0)
@@ -80,24 +72,25 @@ GEM
80
72
  rake (>= 0.8.7)
81
73
  rdoc (~> 3.4)
82
74
  thor (~> 0.14.4)
83
- rake (10.0.4)
75
+ rake (10.4.2)
84
76
  rdoc (3.12.2)
85
77
  json (~> 1.4)
86
78
  thor (0.14.6)
87
- treetop (1.4.12)
79
+ treetop (1.4.15)
88
80
  polyglot
89
81
  polyglot (>= 0.3.1)
90
- tzinfo (0.3.37)
91
- yaggy (0.1.7)
82
+ tzinfo (0.3.42)
83
+ wwtd (0.5.5)
92
84
 
93
85
  PLATFORMS
94
86
  ruby
95
87
 
96
88
  DEPENDENCIES
97
- appraisal
98
89
  ar_mysql_flexmaster!
99
- debugger (~> 1.5.0)
100
- mysql2 (~> 0.2.0)
101
- mysql_isolated_server (~> 0.1.1)
90
+ bump
91
+ minitest
92
+ mysql2 (~> 0.2.0, <= 0.2.18)
93
+ mysql_isolated_server (~> 0.5)
102
94
  rails (~> 3.0.0)
103
- yaggy
95
+ rake
96
+ wwtd
@@ -1,10 +1,7 @@
1
- # This file was generated by Appraisal
2
-
3
1
  source "https://rubygems.org"
4
2
 
5
- gem "debugger", "~>1.5.0"
6
- gem "appraisal"
7
- gem "rails", "~> 3.2.0"
8
- gem "mysql2", "~> 0.3.0"
3
+ gemspec :path => "../"
9
4
 
10
- gemspec :path=>"../"
5
+ gem "rake"
6
+ gem "rails", "~> 3.2.0"
7
+ gem "mysql2", "~> 0.3.0", "<= 0.3.11"
@@ -1,7 +1,7 @@
1
1
  PATH
2
- remote: /Users/ben/src/ar_mysql_flexmaster
2
+ remote: ../
3
3
  specs:
4
- ar_mysql_flexmaster (0.3.1)
4
+ ar_mysql_flexmaster (0.4.4)
5
5
  activerecord
6
6
  activesupport
7
7
  mysql2
@@ -9,12 +9,12 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- actionmailer (3.2.13)
13
- actionpack (= 3.2.13)
14
- mail (~> 2.5.3)
15
- actionpack (3.2.13)
16
- activemodel (= 3.2.13)
17
- activesupport (= 3.2.13)
12
+ actionmailer (3.2.21)
13
+ actionpack (= 3.2.21)
14
+ mail (~> 2.5.4)
15
+ actionpack (3.2.21)
16
+ activemodel (= 3.2.21)
17
+ activesupport (= 3.2.21)
18
18
  builder (~> 3.0.0)
19
19
  erubis (~> 2.7.0)
20
20
  journey (~> 1.0.4)
@@ -22,92 +22,84 @@ GEM
22
22
  rack-cache (~> 1.2)
23
23
  rack-test (~> 0.6.1)
24
24
  sprockets (~> 2.2.1)
25
- activemodel (3.2.13)
26
- activesupport (= 3.2.13)
25
+ activemodel (3.2.21)
26
+ activesupport (= 3.2.21)
27
27
  builder (~> 3.0.0)
28
- activerecord (3.2.13)
29
- activemodel (= 3.2.13)
30
- activesupport (= 3.2.13)
28
+ activerecord (3.2.21)
29
+ activemodel (= 3.2.21)
30
+ activesupport (= 3.2.21)
31
31
  arel (~> 3.0.2)
32
32
  tzinfo (~> 0.3.29)
33
- activeresource (3.2.13)
34
- activemodel (= 3.2.13)
35
- activesupport (= 3.2.13)
36
- activesupport (3.2.13)
37
- i18n (= 0.6.1)
33
+ activeresource (3.2.21)
34
+ activemodel (= 3.2.21)
35
+ activesupport (= 3.2.21)
36
+ activesupport (3.2.21)
37
+ i18n (~> 0.6, >= 0.6.4)
38
38
  multi_json (~> 1.0)
39
- appraisal (0.5.2)
40
- bundler
41
- rake
42
- arel (3.0.2)
39
+ arel (3.0.3)
43
40
  builder (3.0.4)
44
- columnize (0.3.6)
45
- debugger (1.5.0)
46
- columnize (>= 0.3.1)
47
- debugger-linecache (~> 1.2.0)
48
- debugger-ruby_core_source (~> 1.2.0)
49
- debugger-linecache (1.2.0)
50
- debugger-ruby_core_source (1.2.0)
41
+ bump (0.5.1)
51
42
  erubis (2.7.0)
52
- hike (1.2.2)
53
- i18n (0.6.1)
43
+ hike (1.2.3)
44
+ i18n (0.6.11)
54
45
  journey (1.0.4)
55
- json (1.7.7)
56
- mail (2.5.3)
57
- i18n (>= 0.4.0)
46
+ json (1.8.1)
47
+ mail (2.5.4)
58
48
  mime-types (~> 1.16)
59
49
  treetop (~> 1.4.8)
60
- mime-types (1.23)
61
- multi_json (1.7.2)
50
+ mime-types (1.25.1)
51
+ minitest (5.4.3)
52
+ multi_json (1.10.1)
62
53
  mysql2 (0.3.11)
63
- mysql_isolated_server (0.1.1)
64
- polyglot (0.3.3)
54
+ mysql_isolated_server (0.5.3)
55
+ polyglot (0.3.5)
65
56
  rack (1.4.5)
66
57
  rack-cache (1.2)
67
58
  rack (>= 0.4)
68
- rack-ssl (1.3.3)
59
+ rack-ssl (1.3.4)
69
60
  rack
70
61
  rack-test (0.6.2)
71
62
  rack (>= 1.0)
72
- rails (3.2.13)
73
- actionmailer (= 3.2.13)
74
- actionpack (= 3.2.13)
75
- activerecord (= 3.2.13)
76
- activeresource (= 3.2.13)
77
- activesupport (= 3.2.13)
63
+ rails (3.2.21)
64
+ actionmailer (= 3.2.21)
65
+ actionpack (= 3.2.21)
66
+ activerecord (= 3.2.21)
67
+ activeresource (= 3.2.21)
68
+ activesupport (= 3.2.21)
78
69
  bundler (~> 1.0)
79
- railties (= 3.2.13)
80
- railties (3.2.13)
81
- actionpack (= 3.2.13)
82
- activesupport (= 3.2.13)
70
+ railties (= 3.2.21)
71
+ railties (3.2.21)
72
+ actionpack (= 3.2.21)
73
+ activesupport (= 3.2.21)
83
74
  rack-ssl (~> 1.3.2)
84
75
  rake (>= 0.8.7)
85
76
  rdoc (~> 3.4)
86
77
  thor (>= 0.14.6, < 2.0)
87
- rake (10.0.4)
78
+ rake (10.4.2)
88
79
  rdoc (3.12.2)
89
80
  json (~> 1.4)
90
- sprockets (2.2.2)
81
+ sprockets (2.2.3)
91
82
  hike (~> 1.2)
92
83
  multi_json (~> 1.0)
93
84
  rack (~> 1.0)
94
85
  tilt (~> 1.1, != 1.3.0)
95
- thor (0.18.1)
96
- tilt (1.3.7)
97
- treetop (1.4.12)
86
+ thor (0.19.1)
87
+ tilt (1.4.1)
88
+ treetop (1.4.15)
98
89
  polyglot
99
90
  polyglot (>= 0.3.1)
100
- tzinfo (0.3.37)
101
- yaggy (0.1.7)
91
+ tzinfo (0.3.42)
92
+ wwtd (0.5.5)
102
93
 
103
94
  PLATFORMS
104
95
  ruby
105
96
 
106
97
  DEPENDENCIES
107
- appraisal
108
98
  ar_mysql_flexmaster!
109
- debugger (~> 1.5.0)
110
- mysql2 (~> 0.3.0)
111
- mysql_isolated_server (~> 0.1.1)
99
+ bump
100
+ minitest
101
+ mysql2 (~> 0.3.0, <= 0.3.11)
102
+ mysql_isolated_server (~> 0.5)
112
103
  rails (~> 3.2.0)
113
- yaggy
104
+ rake
105
+ wwtd