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: []
         |