ar_mysql_flexmaster 0.4.4 → 0.5.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: 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