ar_mysql_flexmaster 0.3.0 → 0.3.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.
- data/.travis.yml +7 -0
- data/ar_mysql_flexmaster.gemspec +2 -1
- data/gemfiles/rails2.gemfile.lock +3 -1
- data/gemfiles/rails3.2.gemfile.lock +3 -1
- data/gemfiles/rails3.gemfile.lock +3 -1
- data/lib/active_record/connection_adapters/mysql_flexmaster_adapter.rb +3 -3
- data/test/boot_mysql_env.rb +1 -4
- metadata +19 -10
- data/test/mysql_isolated_server.rb +0 -123
- data/test/user.MYD +0 -0
- data/test/user.MYI +0 -0
- data/test/user.frm +0 -0
data/.travis.yml
ADDED
data/ar_mysql_flexmaster.gemspec
CHANGED
@@ -12,11 +12,12 @@ 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.3.
|
15
|
+
gem.version = "0.3.1"
|
16
16
|
|
17
17
|
gem.add_runtime_dependency("mysql2")
|
18
18
|
gem.add_runtime_dependency("activerecord")
|
19
19
|
gem.add_runtime_dependency("activesupport")
|
20
20
|
gem.add_development_dependency("appraisal")
|
21
21
|
gem.add_development_dependency("yaggy")
|
22
|
+
gem.add_development_dependency("mysql_isolated_server")
|
22
23
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: /Users/ben/src/ar_mysql_flexmaster
|
3
3
|
specs:
|
4
|
-
ar_mysql_flexmaster (0.0
|
4
|
+
ar_mysql_flexmaster (0.3.0)
|
5
5
|
activerecord
|
6
6
|
activesupport
|
7
7
|
mysql2
|
@@ -31,6 +31,7 @@ GEM
|
|
31
31
|
debugger-ruby_core_source (>= 1.1.1)
|
32
32
|
debugger-ruby_core_source (1.1.6)
|
33
33
|
mysql2 (0.2.18)
|
34
|
+
mysql_isolated_server (0.0.2)
|
34
35
|
rack (1.1.5)
|
35
36
|
rails (2.3.15)
|
36
37
|
actionmailer (= 2.3.15)
|
@@ -50,5 +51,6 @@ DEPENDENCIES
|
|
50
51
|
ar_mysql_flexmaster!
|
51
52
|
debugger
|
52
53
|
mysql2 (~> 0.2.0)
|
54
|
+
mysql_isolated_server
|
53
55
|
rails (~> 2.3.15)
|
54
56
|
yaggy
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: /Users/ben/src/ar_mysql_flexmaster
|
3
3
|
specs:
|
4
|
-
ar_mysql_flexmaster (0.0
|
4
|
+
ar_mysql_flexmaster (0.3.0)
|
5
5
|
activerecord
|
6
6
|
activesupport
|
7
7
|
mysql2
|
@@ -61,6 +61,7 @@ GEM
|
|
61
61
|
mime-types (1.19)
|
62
62
|
multi_json (1.5.0)
|
63
63
|
mysql2 (0.3.11)
|
64
|
+
mysql_isolated_server (0.0.2)
|
64
65
|
polyglot (0.3.3)
|
65
66
|
rack (1.4.4)
|
66
67
|
rack-cache (1.2)
|
@@ -108,5 +109,6 @@ DEPENDENCIES
|
|
108
109
|
ar_mysql_flexmaster!
|
109
110
|
debugger
|
110
111
|
mysql2 (~> 0.3.0)
|
112
|
+
mysql_isolated_server
|
111
113
|
rails (~> 3.2.0)
|
112
114
|
yaggy
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: /Users/ben/src/ar_mysql_flexmaster
|
3
3
|
specs:
|
4
|
-
ar_mysql_flexmaster (0.0
|
4
|
+
ar_mysql_flexmaster (0.3.0)
|
5
5
|
activerecord
|
6
6
|
activesupport
|
7
7
|
mysql2
|
@@ -60,6 +60,7 @@ GEM
|
|
60
60
|
treetop (~> 1.4.8)
|
61
61
|
mime-types (1.19)
|
62
62
|
mysql2 (0.2.18)
|
63
|
+
mysql_isolated_server (0.0.2)
|
63
64
|
polyglot (0.3.3)
|
64
65
|
rack (1.2.7)
|
65
66
|
rack-mount (0.6.14)
|
@@ -98,5 +99,6 @@ DEPENDENCIES
|
|
98
99
|
ar_mysql_flexmaster!
|
99
100
|
debugger
|
100
101
|
mysql2 (~> 0.2.0)
|
102
|
+
mysql_isolated_server
|
101
103
|
rails (~> 3.0.0)
|
102
104
|
yaggy
|
@@ -24,9 +24,9 @@ module ActiveRecord
|
|
24
24
|
|
25
25
|
module ConnectionAdapters
|
26
26
|
class MysqlFlexmasterAdapter < Mysql2Adapter
|
27
|
-
class NoActiveMasterException <
|
28
|
-
class TooManyMastersException <
|
29
|
-
class NoServerAvailableException <
|
27
|
+
class NoActiveMasterException < StandardError; end
|
28
|
+
class TooManyMastersException < StandardError; end
|
29
|
+
class NoServerAvailableException < StandardError; end
|
30
30
|
|
31
31
|
CHECK_EVERY_N_SELECTS = 10
|
32
32
|
DEFAULT_CONNECT_TIMEOUT = 5
|
data/test/boot_mysql_env.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
3
|
+
require "mysql_isolated_server"
|
4
4
|
|
5
5
|
threads = []
|
6
6
|
threads << Thread.new do
|
7
7
|
$mysql_master = MysqlIsolatedServer.new(allow_output: false)
|
8
8
|
$mysql_master.boot!
|
9
|
-
$mysql_master.connection.query("set global server_id=1")
|
10
9
|
|
11
10
|
puts "mysql master booted on port #{$mysql_master.port} -- access with mysql -uroot -h127.0.0.1 --port=#{$mysql_master.port} mysql"
|
12
11
|
end
|
@@ -14,7 +13,6 @@ end
|
|
14
13
|
threads << Thread.new do
|
15
14
|
$mysql_slave = MysqlIsolatedServer.new
|
16
15
|
$mysql_slave.boot!
|
17
|
-
$mysql_slave.connection.query("set global server_id=2")
|
18
16
|
|
19
17
|
puts "mysql slave booted on port #{$mysql_slave.port} -- access with mysql -uroot -h127.0.0.1 --port=#{$mysql_slave.port} mysql"
|
20
18
|
end
|
@@ -22,7 +20,6 @@ end
|
|
22
20
|
threads << Thread.new do
|
23
21
|
$mysql_slave_2 = MysqlIsolatedServer.new
|
24
22
|
$mysql_slave_2.boot!
|
25
|
-
$mysql_slave_2.connection.query("set global server_id=3")
|
26
23
|
|
27
24
|
puts "mysql chained slave booted on port #{$mysql_slave_2.port} -- access with mysql -uroot -h127.0.0.1 --port=#{$mysql_slave_2.port} mysql"
|
28
25
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ar_mysql_flexmaster
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-04-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mysql2
|
@@ -91,6 +91,22 @@ dependencies:
|
|
91
91
|
- - ! '>='
|
92
92
|
- !ruby/object:Gem::Version
|
93
93
|
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: mysql_isolated_server
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
94
110
|
description: ar_mysql_flexmaster allows configuring N mysql servers in database.yml
|
95
111
|
and auto-selects which is a master at runtime
|
96
112
|
email:
|
@@ -101,6 +117,7 @@ extensions: []
|
|
101
117
|
extra_rdoc_files: []
|
102
118
|
files:
|
103
119
|
- .gitignore
|
120
|
+
- .travis.yml
|
104
121
|
- Appraisals
|
105
122
|
- Gemfile
|
106
123
|
- LICENSE
|
@@ -124,10 +141,6 @@ files:
|
|
124
141
|
- test/integration/there_and_back_again_test.rb
|
125
142
|
- test/integration/with_queries_to_be_killed_test.rb
|
126
143
|
- test/integration/wrong_setup_test.rb
|
127
|
-
- test/mysql_isolated_server.rb
|
128
|
-
- test/user.MYD
|
129
|
-
- test/user.MYI
|
130
|
-
- test/user.frm
|
131
144
|
homepage: http://github.com/osheroff/ar_mysql_flexmaster
|
132
145
|
licenses: []
|
133
146
|
post_install_message:
|
@@ -161,7 +174,3 @@ test_files:
|
|
161
174
|
- test/integration/there_and_back_again_test.rb
|
162
175
|
- test/integration/with_queries_to_be_killed_test.rb
|
163
176
|
- test/integration/wrong_setup_test.rb
|
164
|
-
- test/mysql_isolated_server.rb
|
165
|
-
- test/user.MYD
|
166
|
-
- test/user.MYI
|
167
|
-
- test/user.frm
|
@@ -1,123 +0,0 @@
|
|
1
|
-
require 'tmpdir'
|
2
|
-
require 'socket'
|
3
|
-
require 'mysql2'
|
4
|
-
|
5
|
-
class MysqlIsolatedServer
|
6
|
-
attr_reader :pid, :base, :port
|
7
|
-
MYSQL_BASE_DIR="/usr"
|
8
|
-
|
9
|
-
def initialize(options = {})
|
10
|
-
@base = Dir.mktmpdir("/tmp/mysql_isolated")
|
11
|
-
@mysql_data_dir="#{@base}/mysqld"
|
12
|
-
@mysql_socket="#{@mysql_data_dir}/mysqld.sock"
|
13
|
-
@params = options[:params]
|
14
|
-
@load_data_path = options[:data_path]
|
15
|
-
@port = options[:port]
|
16
|
-
@allow_output = options[:allow_output]
|
17
|
-
end
|
18
|
-
|
19
|
-
def make_slave_of(master)
|
20
|
-
master_binlog_info = master.connection.query("show master status").first
|
21
|
-
connection.query(<<-EOL
|
22
|
-
change master to master_host='127.0.0.1',
|
23
|
-
master_port=#{master.port},
|
24
|
-
master_user='root', master_password='',
|
25
|
-
master_log_file='#{master_binlog_info['File']}',
|
26
|
-
master_log_pos=#{master_binlog_info['Position']}
|
27
|
-
EOL
|
28
|
-
)
|
29
|
-
connection.query("SLAVE START")
|
30
|
-
end
|
31
|
-
|
32
|
-
def connection
|
33
|
-
@cx ||= Mysql2::Client.new(:host => "127.0.0.1", :port => @port, :username => "root", :password => "", :database => "mysql")
|
34
|
-
end
|
35
|
-
|
36
|
-
def set_rw(rw)
|
37
|
-
ro = rw ? 0 : 1
|
38
|
-
connection.query("SET GLOBAL READ_ONLY=#{ro}")
|
39
|
-
end
|
40
|
-
|
41
|
-
|
42
|
-
def locate_executable(*candidates)
|
43
|
-
output = `which #{candidates.join(' ')}`
|
44
|
-
return nil if output == "\n"
|
45
|
-
output.split("\n").first
|
46
|
-
end
|
47
|
-
|
48
|
-
def boot!
|
49
|
-
@port ||= grab_free_port
|
50
|
-
system("rm -Rf #{@mysql_data_dir}")
|
51
|
-
system("mkdir #{@mysql_data_dir}")
|
52
|
-
if @load_data_path
|
53
|
-
system("cp -a #{@load_data_path}/* #{@mysql_data_dir}")
|
54
|
-
system("rm -f #{@mysql_data_dir}/relay-log.info")
|
55
|
-
else
|
56
|
-
mysql_install_db = `which mysql_install_db`
|
57
|
-
idb_path = File.dirname(mysql_install_db)
|
58
|
-
system("(cd #{idb_path}/..; mysql_install_db --datadir=#{@mysql_data_dir} --user=`whoami`) >/dev/null 2>&1")
|
59
|
-
system("cp #{File.expand_path(File.dirname(__FILE__))}/user.* #{@mysql_data_dir}/mysql")
|
60
|
-
end
|
61
|
-
|
62
|
-
exec_server <<-EOL
|
63
|
-
mysqld --no-defaults --default-storage-engine=innodb \
|
64
|
-
--datadir=#{@mysql_data_dir} --pid-file=#{@base}/mysqld.pid --port=#{@port} \
|
65
|
-
#{@params} --socket=#{@mysql_data_dir}/mysql.sock --log-bin --log-slave-updates
|
66
|
-
EOL
|
67
|
-
|
68
|
-
while !system("mysql -h127.0.0.1 --port=#{@port} --database=mysql -u root -e 'select 1' >/dev/null 2>&1")
|
69
|
-
sleep(0.1)
|
70
|
-
end
|
71
|
-
|
72
|
-
tzinfo_to_sql = locate_executable("mysql_tzinfo_to_sql5", "mysql_tzinfo_to_sql")
|
73
|
-
raise "could not find mysql_tzinfo_to_sql" unless tzinfo_to_sql
|
74
|
-
system("#{tzinfo_to_sql} /usr/share/zoneinfo 2>/dev/null | mysql -h127.0.0.1 --database=mysql --port=#{@port} -u root mysql ")
|
75
|
-
|
76
|
-
system(%Q(mysql -h127.0.0.1 --port=#{@port} --database=mysql -u root -e "SET GLOBAL time_zone='UTC'"))
|
77
|
-
system(%Q(mysql -h127.0.0.1 --port=#{@port} --database=mysql -u root -e "GRANT SELECT ON *.* to 'zdslave'@'localhost'"))
|
78
|
-
end
|
79
|
-
|
80
|
-
def grab_free_port
|
81
|
-
while true
|
82
|
-
candidate=9000 + rand(50_000)
|
83
|
-
|
84
|
-
begin
|
85
|
-
socket = Socket.new(:INET, :STREAM, 0)
|
86
|
-
socket.bind(Addrinfo.tcp("127.0.0.1", candidate))
|
87
|
-
socket.close
|
88
|
-
return candidate
|
89
|
-
rescue Exception => e
|
90
|
-
puts e
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
attr_reader :pid
|
96
|
-
def exec_server(cmd)
|
97
|
-
cmd.strip!
|
98
|
-
cmd.gsub!(/\\\n/, ' ')
|
99
|
-
devnull = File.open("/dev/null", "w")
|
100
|
-
system("mkdir -p #{base}/tmp")
|
101
|
-
system("chmod 0777 #{base}/tmp")
|
102
|
-
pid = fork do
|
103
|
-
ENV["TMPDIR"] = "#{base}/tmp"
|
104
|
-
if !@allow_output
|
105
|
-
STDOUT.reopen(devnull)
|
106
|
-
STDERR.reopen(devnull)
|
107
|
-
end
|
108
|
-
|
109
|
-
exec(cmd)
|
110
|
-
end
|
111
|
-
at_exit {
|
112
|
-
Process.kill("TERM", pid)
|
113
|
-
system("rm -Rf #{base}")
|
114
|
-
}
|
115
|
-
@pid = pid
|
116
|
-
devnull.close
|
117
|
-
end
|
118
|
-
|
119
|
-
def kill!
|
120
|
-
return unless @pid
|
121
|
-
system("kill -KILL #{@pid}")
|
122
|
-
end
|
123
|
-
end
|
data/test/user.MYD
DELETED
Binary file
|
data/test/user.MYI
DELETED
Binary file
|
data/test/user.frm
DELETED
Binary file
|