mysql-pause-adapter-ext 0.1.4
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/README +100 -0
- data/lib/mysql-pause/adapter-ext.rb +26 -0
- data/lib/mysql-pause/error.rb +45 -0
- metadata +47 -0
data/README
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
= mysql-pause
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
mysql-pause is a proxy server to pause a query to MySQL.
|
6
|
+
|
7
|
+
== Source Code
|
8
|
+
|
9
|
+
https://bitbucket.org/winebarrel/mysql-pause
|
10
|
+
|
11
|
+
== Dependency
|
12
|
+
|
13
|
+
* EventMachine
|
14
|
+
* RExec
|
15
|
+
|
16
|
+
== Install
|
17
|
+
|
18
|
+
gem install mysql-pause
|
19
|
+
|
20
|
+
== Example
|
21
|
+
=== Start server
|
22
|
+
|
23
|
+
shell> mysql-pause start
|
24
|
+
Starting daemon...
|
25
|
+
Waiting for daemon to start...
|
26
|
+
Daemon status: running pid=56921
|
27
|
+
|
28
|
+
shell> mysql -h 127.0.0.1 -P 13306 -u scott -ptiger
|
29
|
+
mysql> select 1;
|
30
|
+
+---+
|
31
|
+
| 1 |
|
32
|
+
+---+
|
33
|
+
| 1 |
|
34
|
+
+---+
|
35
|
+
1 row in set (0.00 sec)
|
36
|
+
|
37
|
+
=== Pause
|
38
|
+
|
39
|
+
shell> mpctl pause
|
40
|
+
|
41
|
+
mysql> select 1;
|
42
|
+
(...no response...)
|
43
|
+
|
44
|
+
=== Resume
|
45
|
+
|
46
|
+
shell> mpctl resume
|
47
|
+
|
48
|
+
(...resume response...)
|
49
|
+
+---+
|
50
|
+
| 1 |
|
51
|
+
+---+
|
52
|
+
| 1 |
|
53
|
+
+---+
|
54
|
+
1 row in set (18.01 sec)
|
55
|
+
|
56
|
+
== Extend MySQL adapter
|
57
|
+
=== Example code
|
58
|
+
|
59
|
+
require 'active_record'
|
60
|
+
require 'mysql-pause/adapter-ext'
|
61
|
+
|
62
|
+
ActiveRecord::Base.establish_connection(
|
63
|
+
:adapter => 'mysql2',
|
64
|
+
:host => '127.0.0.1',
|
65
|
+
:port => 13306,
|
66
|
+
:username => 'scott',
|
67
|
+
:password => 'tiger',
|
68
|
+
:database => 'employees',
|
69
|
+
:reconnect => true,
|
70
|
+
)
|
71
|
+
|
72
|
+
class Employee < ActiveRecord::Base; end
|
73
|
+
|
74
|
+
loop do
|
75
|
+
employee = Employee.new
|
76
|
+
employee.first_name = 'Taro'
|
77
|
+
employee.last_name = 'Yamada'
|
78
|
+
employee.save!
|
79
|
+
sleep 3
|
80
|
+
end
|
81
|
+
|
82
|
+
=== Behavior
|
83
|
+
|
84
|
+
log> DEBUG -- : (0.6ms) BEGIN
|
85
|
+
log> DEBUG -- : SQL (0.7ms) INSERT INTO `employees` (`first_name`, `last_name`) VALUES ('Taro', 'Yamada')
|
86
|
+
log> DEBUG -- : (0.8ms) COMMIT
|
87
|
+
log> DEBUG -- : (0.6ms) BEGIN
|
88
|
+
|
89
|
+
shell> mpctl pause
|
90
|
+
shell> service mysql restart
|
91
|
+
shell> mpctl resume
|
92
|
+
|
93
|
+
log> DEBUG -- : (0.6ms) BEGIN
|
94
|
+
(...handle error and reconnect...)
|
95
|
+
log> DEBUG -- : Mysql2::Error: %MYSQL_PAUSE%;;1000;;Aborted backend connection: BEGIN
|
96
|
+
log> WARN -- : ActiveRecord::StatementInvalid: Mysql2::Error: %MYSQL_PAUSE%;;1000;;Aborted backend connection: BEGIN
|
97
|
+
log> DEBUG -- : (0.3ms) BEGIN
|
98
|
+
log> DEBUG -- : SQL (2.1ms) INSERT INTO `employees` (`first_name`, `last_name`) VALUES ('Taro', 'Yamada')
|
99
|
+
log> DEBUG -- : (0.8ms) COMMIT
|
100
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_record/connection_adapters/abstract_mysql_adapter'
|
3
|
+
require 'mysql-pause/error'
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module ConnectionAdapters
|
7
|
+
class AbstractMysqlAdapter
|
8
|
+
|
9
|
+
alias mysql_pause_execute_orig execute
|
10
|
+
|
11
|
+
def execute(sql, name = nil)
|
12
|
+
begin
|
13
|
+
mysql_pause_execute_orig(sql, name)
|
14
|
+
rescue => e
|
15
|
+
raise(e) unless MysqlPause::Error.mysql_pause_error?(e)
|
16
|
+
|
17
|
+
message = "#{e.class.name}: #{e.message}"
|
18
|
+
@logger.warn message if @logger
|
19
|
+
reconnect!
|
20
|
+
retry
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end # AbstractMysqlAdapter
|
25
|
+
end # ConnectionAdapters
|
26
|
+
end # ActiveRecord
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module MysqlPause
|
2
|
+
class Error
|
3
|
+
|
4
|
+
ERROR_HEADER = '%MYSQL_PAUSE%'
|
5
|
+
ERROR_SEPARATOR = ';;'
|
6
|
+
ERROR_LIST = {}
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def create_error_message(error_code, sequence_id)
|
10
|
+
# fetch error info
|
11
|
+
mysql_error_code, sql_state, message = ERROR_LIST[error_code]
|
12
|
+
|
13
|
+
# create mysql error message
|
14
|
+
message = [ERROR_HEADER, error_code, message].join(ERROR_SEPARATOR)
|
15
|
+
|
16
|
+
# create header
|
17
|
+
mysql_error_code = convert_to_chars(mysql_error_code, 2)
|
18
|
+
payload = ["\xFF", mysql_error_code, '#', sql_state, message].join
|
19
|
+
payload_length = convert_to_chars(payload.length, 3)
|
20
|
+
sequence_id = convert_to_chars(sequence_id, 1)
|
21
|
+
|
22
|
+
[payload_length, sequence_id, payload].join
|
23
|
+
end
|
24
|
+
|
25
|
+
def mysql_pause_error?(e)
|
26
|
+
/#{Regexp.escape(ERROR_HEADER)}/ =~ e.message
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def convert_to_chars(number, length)
|
32
|
+
(0...length).map {|i| (number >> (8 * i)) & 0xFF }.pack("C*")
|
33
|
+
end
|
34
|
+
|
35
|
+
def define_error(name, code, values)
|
36
|
+
const_set(name, code)
|
37
|
+
ERROR_LIST[code] = values
|
38
|
+
end
|
39
|
+
end # self
|
40
|
+
|
41
|
+
# error list
|
42
|
+
define_error :ABORTED_BACKEND_CONNECTION, 1000, [2013, '08S01', 'Aborted backend connection']
|
43
|
+
|
44
|
+
end # Errot
|
45
|
+
end # MysqlPause
|
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mysql-pause-adapter-ext
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.4
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- winebarrel
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-05-24 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description:
|
15
|
+
email: sgwr_dts@yahoo.co.jp
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- README
|
21
|
+
- lib/mysql-pause/adapter-ext.rb
|
22
|
+
- lib/mysql-pause/error.rb
|
23
|
+
homepage: https://bitbucket.org/winebarrel/mysql-pause
|
24
|
+
licenses: []
|
25
|
+
post_install_message:
|
26
|
+
rdoc_options: []
|
27
|
+
require_paths:
|
28
|
+
- lib
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
requirements: []
|
42
|
+
rubyforge_project:
|
43
|
+
rubygems_version: 1.8.23
|
44
|
+
signing_key:
|
45
|
+
specification_version: 3
|
46
|
+
summary: mysql adapter extension for mysql-pause
|
47
|
+
test_files: []
|