em-pg-client 0.2.0.pre.2 → 0.2.0.pre.3
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/HISTORY.rdoc +10 -1
- data/README.rdoc +1 -1
- data/Rakefile +28 -5
- data/em-pg-client.gemspec +1 -1
- data/lib/em-synchrony/pg.rb +4 -4
- data/lib/pg/em.rb +61 -11
- data/spec/em_client_autoreconnect.rb +124 -0
- data/spec/em_client_common.rb +152 -0
- data/spec/em_devel_client.rb +6 -41
- data/spec/em_release_client.rb +6 -40
- data/spec/em_synchrony_client.rb +120 -9
- data/spec/em_synchrony_client_autoreconnect.rb +118 -0
- metadata +8 -2
    
        data/HISTORY.rdoc
    CHANGED
    
    | @@ -1,3 +1,12 @@ | |
| 1 | 
            +
            0.2.0.pre.3
         | 
| 2 | 
            +
            - #status() returns CONNECTION_BAD for connections with expired query
         | 
| 3 | 
            +
            - spec: query timeout expiration
         | 
| 4 | 
            +
            - non-blocking result processing for multiple data query statements sent at once
         | 
| 5 | 
            +
            - refine code in em-synchrony/pg
         | 
| 6 | 
            +
            - spec: more detailed tests
         | 
| 7 | 
            +
            - spec: async_connect
         | 
| 8 | 
            +
            - spec: autoreconnect
         | 
| 9 | 
            +
             | 
| 1 10 | 
             
            0.2.0.pre.2
         | 
| 2 11 | 
             
            - errors from consume_input fails deferrable
         | 
| 3 12 | 
             
            - query_timeout now measures only network response timeout, 
         | 
| @@ -5,7 +14,7 @@ | |
| 5 14 |  | 
| 6 15 | 
             
            0.2.0.pre.1
         | 
| 7 16 | 
             
            - added query_timeout feature for async query commands
         | 
| 8 | 
            -
            - added connect_timeout property  | 
| 17 | 
            +
            - added connect_timeout property for async connect/reset
         | 
| 9 18 | 
             
            - fix: async_autoreconnect for tcp/ip connections
         | 
| 10 19 | 
             
            - fix: async_* does not raise errors; errors handled by deferrable
         | 
| 11 20 | 
             
            - rework async_autoreconnect in fully async manner
         | 
    
        data/README.rdoc
    CHANGED
    
    
    
        data/Rakefile
    CHANGED
    
    | @@ -4,12 +4,35 @@ task :default => [:test] | |
| 4 4 |  | 
| 5 5 | 
             
            $gem_name = "em-pg-client"
         | 
| 6 6 |  | 
| 7 | 
            -
            desc "Run tests"
         | 
| 8 | 
            -
            task :test do
         | 
| 7 | 
            +
            desc "Run spec tests"
         | 
| 8 | 
            +
            task :test, [:which] do |t, args|
         | 
| 9 | 
            +
              args.with_defaults(:which => 'safe')
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              env_unix_socket = {'PGDATABASE' => 'test', 'PGHOST' => '/tmp'}
         | 
| 12 | 
            +
              env_tcpip = {'PGDATABASE' => 'test', 'PGHOST' => 'localhost'}
         | 
| 13 | 
            +
             | 
| 9 14 | 
             
              puts "WARNING: The test needs to be run with an available local PostgreSQL server"
         | 
| 10 | 
            -
             | 
| 11 | 
            -
               | 
| 12 | 
            -
             | 
| 15 | 
            +
             | 
| 16 | 
            +
              if %w[all safe].include? args[:which]
         | 
| 17 | 
            +
                %w[
         | 
| 18 | 
            +
                  spec/em_release_client.rb
         | 
| 19 | 
            +
                  spec/em_devel_client.rb
         | 
| 20 | 
            +
                  spec/em_synchrony_client.rb
         | 
| 21 | 
            +
                ].each do |spec|
         | 
| 22 | 
            +
                  sh env_unix_socket, "rspec #{spec}"
         | 
| 23 | 
            +
                  sh env_tcpip, "rspec #{spec}"
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              if %w[all unsafe dangerous autoreconnect].include? args[:which]
         | 
| 28 | 
            +
                %w[
         | 
| 29 | 
            +
                  spec/em_client_autoreconnect.rb
         | 
| 30 | 
            +
                  spec/em_synchrony_client_autoreconnect.rb
         | 
| 31 | 
            +
                ].each do |spec|
         | 
| 32 | 
            +
                  sh env_unix_socket, "rspec #{spec}"
         | 
| 33 | 
            +
                  sh env_tcpip, "rspec #{spec}"
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 13 36 | 
             
            end
         | 
| 14 37 |  | 
| 15 38 | 
             
            desc "Build the gem"
         | 
    
        data/em-pg-client.gemspec
    CHANGED
    
    
    
        data/lib/em-synchrony/pg.rb
    CHANGED
    
    | @@ -20,10 +20,10 @@ module PG | |
| 20 20 | 
             
                    class_eval <<-EOD
         | 
| 21 21 | 
             
                      def #{name}(*args, &blk)
         | 
| 22 22 | 
             
                        if ::EM.reactor_running?
         | 
| 23 | 
            -
                          df = #{async_name}(*args)
         | 
| 24 23 | 
             
                          f = Fiber.current
         | 
| 25 | 
            -
                           | 
| 26 | 
            -
             | 
| 24 | 
            +
                          #{async_name}(*args) do |res|
         | 
| 25 | 
            +
                            f.resume(res)
         | 
| 26 | 
            +
                          end
         | 
| 27 27 |  | 
| 28 28 | 
             
                          result = Fiber.yield
         | 
| 29 29 | 
             
                          raise result if result.is_a?(::Exception)
         | 
| @@ -49,7 +49,7 @@ module PG | |
| 49 49 | 
             
                  alias_method :query, :exec
         | 
| 50 50 |  | 
| 51 51 | 
             
                  def async_autoreconnect!(deferrable, error, &send_proc)
         | 
| 52 | 
            -
                     if async_autoreconnect &&  | 
| 52 | 
            +
                     if async_autoreconnect && self.status != PG::CONNECTION_OK
         | 
| 53 53 | 
             
                      reset_df = async_reset
         | 
| 54 54 | 
             
                      reset_df.errback { |ex| deferrable.fail(ex) }
         | 
| 55 55 | 
             
                      reset_df.callback do
         | 
    
        data/lib/pg/em.rb
    CHANGED
    
    | @@ -1,5 +1,34 @@ | |
| 1 1 | 
             
            require 'pg'
         | 
| 2 2 | 
             
            module PG
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              class Result
         | 
| 5 | 
            +
                class << self
         | 
| 6 | 
            +
                  unless method_defined? :check_result
         | 
| 7 | 
            +
                    # pg_check_result is internal ext function. I wish it was rubified.
         | 
| 8 | 
            +
                    # https://bitbucket.org/ged/ruby-pg/issue/123/rubify-pg_check_result
         | 
| 9 | 
            +
                    def check_result(connection, result)
         | 
| 10 | 
            +
                      if result.nil?
         | 
| 11 | 
            +
                        if (error_message = connection.error_message)
         | 
| 12 | 
            +
                          error = PG::Error.new(error_message)
         | 
| 13 | 
            +
                        end
         | 
| 14 | 
            +
                      else
         | 
| 15 | 
            +
                        case result.result_status
         | 
| 16 | 
            +
                          when PG::PGRES_BAD_RESPONSE,
         | 
| 17 | 
            +
                               PG::PGRES_FATAL_ERROR,
         | 
| 18 | 
            +
                               PG::PGRES_NONFATAL_ERROR
         | 
| 19 | 
            +
                            error = PG::Error.new(result.error_message)
         | 
| 20 | 
            +
                            error.instance_variable_set('@result', result)
         | 
| 21 | 
            +
                        end
         | 
| 22 | 
            +
                      end
         | 
| 23 | 
            +
                      if error
         | 
| 24 | 
            +
                        error.instance_variable_set('@connection', connection)
         | 
| 25 | 
            +
                        raise error 
         | 
| 26 | 
            +
                      end
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 3 32 | 
             
              module EM
         | 
| 4 33 | 
             
                class FeaturedDeferrable < ::EM::DefaultDeferrable
         | 
| 5 34 | 
             
                  def initialize(&blk)
         | 
| @@ -131,6 +160,7 @@ module PG | |
| 131 160 |  | 
| 132 161 | 
             
                  module Watcher
         | 
| 133 162 | 
             
                    def initialize(client, deferrable, send_proc)
         | 
| 163 | 
            +
                      @last_result = nil
         | 
| 134 164 | 
             
                      @client = client
         | 
| 135 165 | 
             
                      @deferrable = deferrable
         | 
| 136 166 | 
             
                      @send_proc = send_proc
         | 
| @@ -158,21 +188,33 @@ module PG | |
| 158 188 | 
             
                    end
         | 
| 159 189 |  | 
| 160 190 | 
             
                    def notify_readable
         | 
| 161 | 
            -
                       | 
| 191 | 
            +
                      result = false
         | 
| 162 192 | 
             
                      @client.consume_input
         | 
| 163 | 
            -
                       | 
| 164 | 
            -
                         | 
| 165 | 
            -
             | 
| 166 | 
            -
                        @ | 
| 193 | 
            +
                      until @client.is_busy && !self.error?
         | 
| 194 | 
            +
                        break if (single_result = @client.get_result).nil?
         | 
| 195 | 
            +
                        @last_result.clear if @last_result
         | 
| 196 | 
            +
                        @last_result = single_result
         | 
| 197 | 
            +
                      end
         | 
| 198 | 
            +
                      unless @client.is_busy
         | 
| 199 | 
            +
                        result = @last_result
         | 
| 200 | 
            +
                        Result.check_result(@client, result)
         | 
| 167 201 | 
             
                        detach
         | 
| 168 | 
            -
                        @ | 
| 202 | 
            +
                        @timer.cancel if @timer
         | 
| 169 203 | 
             
                      end
         | 
| 170 | 
            -
                    rescue PG::Error => e
         | 
| 171 | 
            -
                      @client.async_autoreconnect!(@deferrable, e, &@send_proc)
         | 
| 172 204 | 
             
                    rescue Exception => e
         | 
| 173 | 
            -
                       | 
| 205 | 
            +
                      detach
         | 
| 206 | 
            +
                      @timer.cancel if @timer
         | 
| 207 | 
            +
                      if e.is_a?(PG::Error)
         | 
| 208 | 
            +
                        @client.async_autoreconnect!(@deferrable, e, &@send_proc)
         | 
| 209 | 
            +
                      else
         | 
| 210 | 
            +
                        @deferrable.fail(e)
         | 
| 211 | 
            +
                      end
         | 
| 174 212 | 
             
                    else
         | 
| 175 | 
            -
                       | 
| 213 | 
            +
                      if result == false
         | 
| 214 | 
            +
                        @notify_timestamp = Time.now if @timer
         | 
| 215 | 
            +
                      else
         | 
| 216 | 
            +
                        @deferrable.succeed(result) 
         | 
| 217 | 
            +
                      end
         | 
| 176 218 | 
             
                    end
         | 
| 177 219 | 
             
                  end
         | 
| 178 220 |  | 
| @@ -290,9 +332,17 @@ module PG | |
| 290 332 | 
             
                    super(*args)
         | 
| 291 333 | 
             
                  end
         | 
| 292 334 |  | 
| 335 | 
            +
                  def status
         | 
| 336 | 
            +
                    if @async_command_aborted
         | 
| 337 | 
            +
                      PG::CONNECTION_BAD
         | 
| 338 | 
            +
                    else
         | 
| 339 | 
            +
                      super
         | 
| 340 | 
            +
                    end
         | 
| 341 | 
            +
                  end
         | 
| 342 | 
            +
             | 
| 293 343 | 
             
                  # Perform autoreconnect. Used internally.
         | 
| 294 344 | 
             
                  def async_autoreconnect!(deferrable, error, &send_proc)
         | 
| 295 | 
            -
                    if async_autoreconnect &&  | 
| 345 | 
            +
                    if async_autoreconnect && self.status != PG::CONNECTION_OK
         | 
| 296 346 | 
             
                      reset_df = async_reset
         | 
| 297 347 | 
             
                      reset_df.errback { |ex| deferrable.fail(ex) }
         | 
| 298 348 | 
             
                      reset_df.callback do
         | 
| @@ -0,0 +1,124 @@ | |
| 1 | 
            +
            $:.unshift "lib"
         | 
| 2 | 
            +
            require 'date'
         | 
| 3 | 
            +
            require 'eventmachine'
         | 
| 4 | 
            +
            require 'pg/em'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            $pgserver_cmd_stop = %Q[sudo su - postgres -c 'pg_ctl stop -m fast']
         | 
| 7 | 
            +
            $pgserver_cmd_start = %Q[sudo su - postgres -c 'pg_ctl -l $PGDATA/postgres.log start -w']
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            shared_context 'em-pg common' do
         | 
| 10 | 
            +
              around(:each) do |testcase|
         | 
| 11 | 
            +
                EM.run(&testcase)
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              after(:all) do
         | 
| 15 | 
            +
                @client.close
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            describe 'em-pg default autoreconnect' do
         | 
| 20 | 
            +
              include_context 'em-pg common'
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              it "should get database size using query" do
         | 
| 23 | 
            +
                @tested_proc.call
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              it "should get database size using query after server restart" do
         | 
| 27 | 
            +
                system($pgserver_cmd_stop).should be_true
         | 
| 28 | 
            +
                system($pgserver_cmd_start).should be_true
         | 
| 29 | 
            +
                @tested_proc.call
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              it "should not get database size using query after server shutdown" do
         | 
| 33 | 
            +
                system($pgserver_cmd_stop).should be_true
         | 
| 34 | 
            +
                @client.query('SELECT pg_database_size(current_database());') do |ex|
         | 
| 35 | 
            +
                  ex.should be_an_instance_of PG::Error
         | 
| 36 | 
            +
                  EM.stop
         | 
| 37 | 
            +
                end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              it "should get database size using query after server startup" do
         | 
| 41 | 
            +
                system($pgserver_cmd_start).should be_true
         | 
| 42 | 
            +
                @tested_proc.call
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              before(:all) do
         | 
| 46 | 
            +
                @tested_proc = proc do
         | 
| 47 | 
            +
                  @client.query('SELECT pg_database_size(current_database());') do |result|
         | 
| 48 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 49 | 
            +
                    result[0]['pg_database_size'].to_i.should be > 0
         | 
| 50 | 
            +
                    EM.stop
         | 
| 51 | 
            +
                  end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
                @client = PG::EM::Client.new
         | 
| 54 | 
            +
                @client.set_notice_processor {|msg| puts "warning from pgsql: #{msg.to_s.chomp.inspect}"}
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
            end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            describe 'em-pg autoreconnect with on_autoreconnect' do
         | 
| 59 | 
            +
              include_context 'em-pg common'
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              it "should get database size using prepared statement"do
         | 
| 62 | 
            +
                @tested_proc.call
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
              it "should get database size using prepared statement after server restart" do
         | 
| 66 | 
            +
                system($pgserver_cmd_stop).should be_true
         | 
| 67 | 
            +
                system($pgserver_cmd_start).should be_true
         | 
| 68 | 
            +
                @tested_proc.call
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              before(:all) do
         | 
| 72 | 
            +
                @tested_proc = proc do
         | 
| 73 | 
            +
                  @client.exec_prepared('get_db_size') do |result|
         | 
| 74 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 75 | 
            +
                    result[0]['pg_database_size'].to_i.should be > 0
         | 
| 76 | 
            +
                    EM.stop
         | 
| 77 | 
            +
                  end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
                on_autoreconnect = proc do |client, ex|
         | 
| 80 | 
            +
                  df = client.prepare('get_db_size', 'SELECT pg_database_size(current_database());')
         | 
| 81 | 
            +
                  df.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 82 | 
            +
                  df
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
                @client = PG::EM::Client.new(on_autoreconnect: on_autoreconnect)
         | 
| 85 | 
            +
                @client.set_notice_processor {|msg| puts "warning from pgsql: #{msg.to_s.chomp.inspect}"}
         | 
| 86 | 
            +
                @client.prepare('get_db_size', 'SELECT pg_database_size(current_database());')
         | 
| 87 | 
            +
              end
         | 
| 88 | 
            +
            end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
            describe 'em-pg with autoreconnect disabled' do
         | 
| 91 | 
            +
              include_context 'em-pg common'
         | 
| 92 | 
            +
             | 
| 93 | 
            +
              it "should get database size using query" do
         | 
| 94 | 
            +
                @tested_proc.call
         | 
| 95 | 
            +
              end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
              it "should not get database size using query after server restart" do
         | 
| 98 | 
            +
                system($pgserver_cmd_stop).should be_true
         | 
| 99 | 
            +
                system($pgserver_cmd_start).should be_true
         | 
| 100 | 
            +
                @client.query('SELECT pg_database_size(current_database());') do |ex|
         | 
| 101 | 
            +
                  ex.should be_an_instance_of PG::Error
         | 
| 102 | 
            +
                  EM.stop
         | 
| 103 | 
            +
                end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 104 | 
            +
              end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
              it "should get database size using query after async manual connection reset" do
         | 
| 107 | 
            +
                @client.async_reset do |conn|
         | 
| 108 | 
            +
                  conn.should be @client
         | 
| 109 | 
            +
                  @tested_proc.call
         | 
| 110 | 
            +
                end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 111 | 
            +
              end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
              before(:all) do
         | 
| 114 | 
            +
                @tested_proc = proc do
         | 
| 115 | 
            +
                  @client.query('SELECT pg_database_size(current_database());') do |result|
         | 
| 116 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 117 | 
            +
                    result[0]['pg_database_size'].to_i.should be > 0
         | 
| 118 | 
            +
                    EM.stop
         | 
| 119 | 
            +
                  end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
                @client = PG::EM::Client.new(async_autoreconnect: false)
         | 
| 122 | 
            +
                @client.set_notice_processor {|msg| puts "warning from pgsql: #{msg.to_s.chomp.inspect}"}
         | 
| 123 | 
            +
              end
         | 
| 124 | 
            +
            end
         | 
| @@ -0,0 +1,152 @@ | |
| 1 | 
            +
            shared_context 'em-pg common before' do
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              around(:each) do |testcase|
         | 
| 4 | 
            +
                EM.run &testcase
         | 
| 5 | 
            +
              end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              before(:all) do
         | 
| 8 | 
            +
                @cdates = []
         | 
| 9 | 
            +
                @values = Array(('AA'..'ZZ').each_with_index)
         | 
| 10 | 
            +
                @client = described_class.new
         | 
| 11 | 
            +
                @client.query 'BEGIN TRANSACTION'
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              after(:all) do
         | 
| 15 | 
            +
                @client.query 'ROLLBACK TRANSACTION'
         | 
| 16 | 
            +
                @client.close
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              it "should be a client" do
         | 
| 20 | 
            +
                @client.should be_an_instance_of described_class
         | 
| 21 | 
            +
                EM.stop
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              it "should create simple table `foo`" do
         | 
| 25 | 
            +
                @client.query('DROP TABLE IF EXISTS foo') do |result|
         | 
| 26 | 
            +
                  result.should be_an_instance_of PG::Result
         | 
| 27 | 
            +
                  @client.query('CREATE TABLE foo (id integer,cdate timestamp with time zone,data varchar)') do |result|
         | 
| 28 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 29 | 
            +
                    EM.stop
         | 
| 30 | 
            +
                  end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 31 | 
            +
                end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            shared_context 'em-pg common after' do
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              it "should read foo table with prepared statement" do
         | 
| 39 | 
            +
                @client.prepare('get_foo', 'SELECT * FROM foo order by id') do |result|
         | 
| 40 | 
            +
                  result.should be_an_instance_of PG::Result
         | 
| 41 | 
            +
                  @client.exec_prepared('get_foo') do |result|
         | 
| 42 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 43 | 
            +
                    result.each_with_index do |row, i|
         | 
| 44 | 
            +
                      row['id'].to_i.should == i
         | 
| 45 | 
            +
                      DateTime.parse(row['cdate']).should == @cdates[i]
         | 
| 46 | 
            +
                      row['data'].should == @values[i][0]
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
                    EM.stop
         | 
| 49 | 
            +
                  end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 50 | 
            +
                end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              it "should connect to database asynchronously" do
         | 
| 54 | 
            +
                this = :first
         | 
| 55 | 
            +
                described_class.async_connect do |conn|
         | 
| 56 | 
            +
                  this = :second
         | 
| 57 | 
            +
                  conn.should be_an_instance_of described_class
         | 
| 58 | 
            +
                  conn.query('SELECT pg_database_size(current_database());') do |result|
         | 
| 59 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 60 | 
            +
                    result[0]['pg_database_size'].to_i.should be > 0
         | 
| 61 | 
            +
                    EM.stop
         | 
| 62 | 
            +
                  end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 63 | 
            +
                end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 64 | 
            +
                this.should be :first
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              it "should raise syntax error in misspelled multiple statement" do
         | 
| 68 | 
            +
                @client.query('SELECT * from pg_class; SRELECT CURRENT_TIMESTAMP; SELECT 42 number') do |result|
         | 
| 69 | 
            +
                  result.should be_an_instance_of PG::Error
         | 
| 70 | 
            +
                  result.to_s.should include "syntax error"
         | 
| 71 | 
            +
                  @client.query('ROLLBACK') do |result|
         | 
| 72 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 73 | 
            +
                    @client.query('BEGIN TRANSACTION') do |result|
         | 
| 74 | 
            +
                      result.should be_an_instance_of PG::Result
         | 
| 75 | 
            +
                      EM.stop
         | 
| 76 | 
            +
                    end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 77 | 
            +
                  end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 78 | 
            +
                end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              it "should return only last statement" do
         | 
| 82 | 
            +
                @client.query('SELECT * from pg_class; SELECT CURRENT_TIMESTAMP; SELECT 42 number') do |result|
         | 
| 83 | 
            +
                  result.should be_an_instance_of PG::Result
         | 
| 84 | 
            +
                  result[0]['number'].should eq "42"
         | 
| 85 | 
            +
                  EM.stop
         | 
| 86 | 
            +
                end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 87 | 
            +
              end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
              it "should timeout expire while executing query" do
         | 
| 90 | 
            +
                @client.query_timeout.should eq 0
         | 
| 91 | 
            +
                @client.query_timeout = 1.5
         | 
| 92 | 
            +
                @client.query_timeout.should eq 1.5
         | 
| 93 | 
            +
                start_time = Time.now
         | 
| 94 | 
            +
                @client.query('SELECT pg_sleep(2)') do |result|
         | 
| 95 | 
            +
                  (Time.now - start_time).should be < 2
         | 
| 96 | 
            +
                  result.should be_an_instance_of PG::Error
         | 
| 97 | 
            +
                  result.to_s.should include "query timeout expired"
         | 
| 98 | 
            +
                  @client.async_command_aborted.should be_true
         | 
| 99 | 
            +
                  @client.query_timeout = 0
         | 
| 100 | 
            +
                  @client.query_timeout.should eq 0
         | 
| 101 | 
            +
                  @client.query('BEGIN TRANSACTION') do |result|
         | 
| 102 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 103 | 
            +
                    EM.stop
         | 
| 104 | 
            +
                  end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 105 | 
            +
                end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 106 | 
            +
              end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
              it "should timeout not expire while executing query with partial results" do
         | 
| 109 | 
            +
                @client.query_timeout.should eq 0
         | 
| 110 | 
            +
                @client.query_timeout = 1.1
         | 
| 111 | 
            +
                @client.query_timeout.should eq 1.1
         | 
| 112 | 
            +
                start_time = Time.now
         | 
| 113 | 
            +
                @client.query(
         | 
| 114 | 
            +
                    'SELECT * from pg_class;' +
         | 
| 115 | 
            +
                    'SELECT pg_sleep(1);' +
         | 
| 116 | 
            +
                    'SELECT * from pg_class;' + 
         | 
| 117 | 
            +
                    'SELECT pg_sleep(1);' +
         | 
| 118 | 
            +
                    'SELECT 42 number') do |result|
         | 
| 119 | 
            +
                  (Time.now - start_time).should be > 2
         | 
| 120 | 
            +
                  result.should be_an_instance_of PG::Result
         | 
| 121 | 
            +
                  result[0]['number'].should eq "42"
         | 
| 122 | 
            +
                  @client.query_timeout = 0
         | 
| 123 | 
            +
                  @client.query_timeout.should eq 0
         | 
| 124 | 
            +
                  @client.async_command_aborted.should be_false
         | 
| 125 | 
            +
                  EM.stop
         | 
| 126 | 
            +
                end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 127 | 
            +
              end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
              it "should timeout expire while executing query with partial results" do
         | 
| 130 | 
            +
                @client.query_timeout.should eq 0
         | 
| 131 | 
            +
                @client.query_timeout = 1.1
         | 
| 132 | 
            +
                @client.query_timeout.should eq 1.1
         | 
| 133 | 
            +
                start_time = Time.now
         | 
| 134 | 
            +
                @client.query(
         | 
| 135 | 
            +
                    'SELECT * from pg_class;' +
         | 
| 136 | 
            +
                    'SELECT pg_sleep(1);' +
         | 
| 137 | 
            +
                    'SELECT * from pg_class;' + 
         | 
| 138 | 
            +
                    'SELECT pg_sleep(2);' +
         | 
| 139 | 
            +
                    'SELECT 42 number') do |result|
         | 
| 140 | 
            +
                  (Time.now - start_time).should be > 2
         | 
| 141 | 
            +
                  result.should be_an_instance_of PG::Error
         | 
| 142 | 
            +
                  result.to_s.should include "query timeout expired"
         | 
| 143 | 
            +
                  @client.query_timeout = 0
         | 
| 144 | 
            +
                  @client.query_timeout.should eq 0
         | 
| 145 | 
            +
                  @client.query('BEGIN TRANSACTION') do |result|
         | 
| 146 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 147 | 
            +
                    EM.stop
         | 
| 148 | 
            +
                  end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 149 | 
            +
                end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 150 | 
            +
              end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
            end
         | 
    
        data/spec/em_devel_client.rb
    CHANGED
    
    | @@ -3,61 +3,26 @@ gem 'eventmachine', '>= 1.0.0.beta.1' | |
| 3 3 | 
             
            require 'date'
         | 
| 4 4 | 
             
            require 'eventmachine'
         | 
| 5 5 | 
             
            require 'pg/em'
         | 
| 6 | 
            +
            require 'em_client_common'
         | 
| 6 7 |  | 
| 7 8 | 
             
            describe PG::EM::Client do
         | 
| 8 9 |  | 
| 9 | 
            -
               | 
| 10 | 
            -
                @client.query('DROP TABLE IF EXISTS foo') do |result|
         | 
| 11 | 
            -
                  raise result if result.is_a? ::Exception
         | 
| 12 | 
            -
                  @client.query('CREATE TABLE foo (id integer,cdate timestamp with time zone,data varchar)') do |result|
         | 
| 13 | 
            -
                    raise result if result.is_a? ::Exception
         | 
| 14 | 
            -
                    EM.stop
         | 
| 15 | 
            -
                  end
         | 
| 16 | 
            -
                end
         | 
| 17 | 
            -
              end
         | 
| 10 | 
            +
              include_context 'em-pg common before'
         | 
| 18 11 |  | 
| 19 12 | 
             
              it "should populate foo with some data " do
         | 
| 20 13 | 
             
                EM::Iterator.new(@values).map(proc{ |(data, id), iter|
         | 
| 21 14 | 
             
                  @client.query('INSERT INTO foo (id,cdate,data) VALUES($1,$2,$3) returning cdate', [id, DateTime.now, data]) do |result|
         | 
| 22 | 
            -
             | 
| 15 | 
            +
                  result.should be_an_instance_of PG::Result
         | 
| 23 16 | 
             
                    iter.return(DateTime.parse(result[0]['cdate']))
         | 
| 24 | 
            -
                  end
         | 
| 17 | 
            +
                  end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 25 18 | 
             
                }, proc{ |results|
         | 
| 26 19 | 
             
                  @cdates.replace results
         | 
| 27 20 | 
             
                  results.length.should == @values.length
         | 
| 28 | 
            -
                  results.each {|r| r. | 
| 21 | 
            +
                  results.each {|r| r.should be_an_instance_of DateTime }
         | 
| 29 22 | 
             
                  EM.stop
         | 
| 30 23 | 
             
                })
         | 
| 31 24 | 
             
              end
         | 
| 32 25 |  | 
| 33 | 
            -
               | 
| 34 | 
            -
                @client.prepare('get_foo', 'SELECT * FROM foo order by id') do |result|
         | 
| 35 | 
            -
                  raise result if result.is_a? ::Exception
         | 
| 36 | 
            -
                  @client.exec_prepared('get_foo') do |result|
         | 
| 37 | 
            -
                    raise result if result.is_a? ::Exception
         | 
| 38 | 
            -
                    result.each_with_index do |row, i|
         | 
| 39 | 
            -
                      row['id'].to_i.should == i
         | 
| 40 | 
            -
                      DateTime.parse(row['cdate']).should == @cdates[i]
         | 
| 41 | 
            -
                      row['data'].should == @values[i][0]
         | 
| 42 | 
            -
                    end
         | 
| 43 | 
            -
                    EM.stop
         | 
| 44 | 
            -
                  end
         | 
| 45 | 
            -
                end
         | 
| 46 | 
            -
              end
         | 
| 47 | 
            -
              
         | 
| 48 | 
            -
              around(:each) do |testcase|
         | 
| 49 | 
            -
                EM.run &testcase
         | 
| 50 | 
            -
              end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
              before(:all) do
         | 
| 53 | 
            -
                @cdates = []
         | 
| 54 | 
            -
                @values = Array(('AA'..'ZZ').each_with_index)
         | 
| 55 | 
            -
                @client = PG::EM::Client.new(dbname: 'test')
         | 
| 56 | 
            -
                @client.query 'BEGIN TRANSACTION'
         | 
| 57 | 
            -
              end
         | 
| 26 | 
            +
              include_context 'em-pg common after'
         | 
| 58 27 |  | 
| 59 | 
            -
              after(:all) do
         | 
| 60 | 
            -
                @client.query 'ROLLBACK TRANSACTION'
         | 
| 61 | 
            -
                @client.close
         | 
| 62 | 
            -
              end
         | 
| 63 28 | 
             
            end
         | 
    
        data/spec/em_release_client.rb
    CHANGED
    
    | @@ -3,18 +3,11 @@ gem 'eventmachine', '= 0.12.10' | |
| 3 3 | 
             
            require 'date'
         | 
| 4 4 | 
             
            require 'eventmachine'
         | 
| 5 5 | 
             
            require 'pg/em'
         | 
| 6 | 
            +
            require 'em_client_common'
         | 
| 6 7 |  | 
| 7 8 | 
             
            describe PG::EM::Client do
         | 
| 8 9 |  | 
| 9 | 
            -
               | 
| 10 | 
            -
                @client.query('DROP TABLE IF EXISTS foo') do |result|
         | 
| 11 | 
            -
                  raise result if result.is_a? ::Exception
         | 
| 12 | 
            -
                  @client.query('CREATE TABLE foo (id integer,cdate timestamp with time zone,data varchar)') do |result|
         | 
| 13 | 
            -
                    raise result if result.is_a? ::Exception
         | 
| 14 | 
            -
                    EM.stop
         | 
| 15 | 
            -
                  end
         | 
| 16 | 
            -
                end
         | 
| 17 | 
            -
              end
         | 
| 10 | 
            +
              include_context 'em-pg common before'
         | 
| 18 11 |  | 
| 19 12 | 
             
              it "should populate foo with some data " do
         | 
| 20 13 | 
             
                values = @values.dup
         | 
| @@ -22,48 +15,21 @@ describe PG::EM::Client do | |
| 22 15 | 
             
                do_query = proc do
         | 
| 23 16 | 
             
                  data, id = values.shift
         | 
| 24 17 | 
             
                  @client.query('INSERT INTO foo (id,cdate,data) VALUES($1,$2,$3) returning cdate', [id, DateTime.now, data]) do |result|
         | 
| 25 | 
            -
                     | 
| 18 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 26 19 | 
             
                    results << DateTime.parse(result[0]['cdate'])
         | 
| 27 20 | 
             
                    if values.empty?
         | 
| 28 21 | 
             
                      @cdates.replace results
         | 
| 29 22 | 
             
                      results.length.should == @values.length
         | 
| 30 | 
            -
                      results.each {|r| r. | 
| 23 | 
            +
                      results.each {|r| r.should be_an_instance_of DateTime }
         | 
| 31 24 | 
             
                      EM.stop
         | 
| 32 25 | 
             
                    else
         | 
| 33 26 | 
             
                      do_query.call
         | 
| 34 27 | 
             
                    end
         | 
| 35 | 
            -
                  end
         | 
| 28 | 
            +
                  end.should be_a_kind_of ::EM::DefaultDeferrable
         | 
| 36 29 | 
             
                end
         | 
| 37 30 | 
             
                do_query.call
         | 
| 38 31 | 
             
              end
         | 
| 39 32 |  | 
| 40 | 
            -
               | 
| 41 | 
            -
                @client.prepare('get_foo', 'SELECT * FROM foo order by id') do
         | 
| 42 | 
            -
                  @client.exec_prepared('get_foo') do |result|
         | 
| 43 | 
            -
                    raise result if result.is_a? ::Exception
         | 
| 44 | 
            -
                    result.each_with_index do |row, i|
         | 
| 45 | 
            -
                      row['id'].to_i.should == i
         | 
| 46 | 
            -
                      DateTime.parse(row['cdate']).should == @cdates[i]
         | 
| 47 | 
            -
                      row['data'].should == @values[i][0]
         | 
| 48 | 
            -
                    end
         | 
| 49 | 
            -
                    EM.stop
         | 
| 50 | 
            -
                  end
         | 
| 51 | 
            -
                end
         | 
| 52 | 
            -
              end
         | 
| 53 | 
            -
              
         | 
| 54 | 
            -
              around(:each) do |testcase|
         | 
| 55 | 
            -
                EM.run &testcase
         | 
| 56 | 
            -
              end
         | 
| 57 | 
            -
             | 
| 58 | 
            -
              before(:all) do
         | 
| 59 | 
            -
                @cdates = []
         | 
| 60 | 
            -
                @values = Array(('AA'..'ZZ').each_with_index)
         | 
| 61 | 
            -
                @client = PG::EM::Client.new(dbname: 'test')
         | 
| 62 | 
            -
                @client.query 'BEGIN TRANSACTION'
         | 
| 63 | 
            -
              end
         | 
| 33 | 
            +
              include_context 'em-pg common after'
         | 
| 64 34 |  | 
| 65 | 
            -
              after(:all) do
         | 
| 66 | 
            -
                @client.query 'ROLLBACK TRANSACTION'
         | 
| 67 | 
            -
                @client.close
         | 
| 68 | 
            -
              end
         | 
| 69 35 | 
             
            end
         | 
    
        data/spec/em_synchrony_client.rb
    CHANGED
    
    | @@ -5,44 +5,155 @@ require 'em-synchrony/pg' | |
| 5 5 |  | 
| 6 6 | 
             
            describe PG::EM::Client do
         | 
| 7 7 |  | 
| 8 | 
            +
              it "should be client" do
         | 
| 9 | 
            +
                @client.should be_an_instance_of described_class
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 8 12 | 
             
              it "should create simple table `foo`" do
         | 
| 9 | 
            -
                @client.query( | 
| 10 | 
            -
             | 
| 11 | 
            -
                 | 
| 13 | 
            +
                @client.query(
         | 
| 14 | 
            +
                  'DROP TABLE IF EXISTS foo'
         | 
| 15 | 
            +
                ).should be_an_instance_of PG::Result
         | 
| 16 | 
            +
                @client.query(
         | 
| 17 | 
            +
                  'CREATE TABLE foo (id integer,cdate timestamp with time zone,data varchar)'
         | 
| 18 | 
            +
                ).should be_an_instance_of PG::Result
         | 
| 12 19 | 
             
              end
         | 
| 13 20 |  | 
| 14 21 | 
             
              it "should populate foo with some data " do
         | 
| 15 22 | 
             
                results = @values.map do |(data, id)|
         | 
| 16 23 | 
             
                  @client.query('INSERT INTO foo (id,cdate,data) VALUES($1,$2,$3) returning cdate', [id, DateTime.now, data]) do |result|
         | 
| 24 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 17 25 | 
             
                    DateTime.parse(result[0]['cdate'])
         | 
| 18 26 | 
             
                  end
         | 
| 19 27 | 
             
                end
         | 
| 20 28 | 
             
                @cdates.replace results
         | 
| 21 29 | 
             
                results.length.should == @values.length
         | 
| 22 | 
            -
                results.each {|r| r. | 
| 23 | 
            -
                EM.stop
         | 
| 30 | 
            +
                results.each {|r| r.should be_an_instance_of DateTime }
         | 
| 24 31 | 
             
              end
         | 
| 25 32 |  | 
| 26 33 | 
             
              it "should read foo table with prepared statement" do
         | 
| 27 | 
            -
                @client.prepare('get_foo',  | 
| 34 | 
            +
                @client.prepare('get_foo', 
         | 
| 35 | 
            +
                  'SELECT * FROM foo order by id'
         | 
| 36 | 
            +
                ).should be_an_instance_of PG::Result
         | 
| 28 37 | 
             
                @client.exec_prepared('get_foo') do |result|
         | 
| 38 | 
            +
                  result.should be_an_instance_of PG::Result
         | 
| 29 39 | 
             
                  result.each_with_index do |row, i|
         | 
| 30 40 | 
             
                    row['id'].to_i.should == i
         | 
| 31 41 | 
             
                    DateTime.parse(row['cdate']).should == @cdates[i]
         | 
| 32 42 | 
             
                    row['data'].should == @values[i][0]
         | 
| 33 43 | 
             
                  end
         | 
| 34 44 | 
             
                end
         | 
| 35 | 
            -
             | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              it "should connect to database asynchronously" do
         | 
| 48 | 
            +
                this = :first
         | 
| 49 | 
            +
                f = Fiber.current
         | 
| 50 | 
            +
                Fiber.new do
         | 
| 51 | 
            +
                  conn = described_class.new
         | 
| 52 | 
            +
                  this = :second
         | 
| 53 | 
            +
                  conn.should be_an_instance_of described_class
         | 
| 54 | 
            +
                  conn.query('SELECT pg_database_size(current_database());') do |result|
         | 
| 55 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 56 | 
            +
                    result[0]['pg_database_size'].to_i.should be > 0
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                  conn.close
         | 
| 59 | 
            +
                  f.resume
         | 
| 60 | 
            +
                end.resume
         | 
| 61 | 
            +
                this.should be :first
         | 
| 62 | 
            +
                Fiber.yield
         | 
| 63 | 
            +
                this.should be :second
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              it "should raise syntax error in misspelled multiple statement" do
         | 
| 67 | 
            +
                expect {
         | 
| 68 | 
            +
                  @client.query('SELECT * from pg_class; SRELECT CURRENT_TIMESTAMP; SELECT 42 number')
         | 
| 69 | 
            +
                }.to raise_error(PG::Error, /syntax error/)
         | 
| 70 | 
            +
                @client.query('ROLLBACK') do |result|
         | 
| 71 | 
            +
                  result.should be_an_instance_of PG::Result
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
                @client.query('BEGIN TRANSACTION') do |result|
         | 
| 74 | 
            +
                  result.should be_an_instance_of PG::Result
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
              it "should return only last statement" do
         | 
| 79 | 
            +
                @client.query('SELECT * from pg_class; SELECT CURRENT_TIMESTAMP; SELECT 42 number') do |result|
         | 
| 80 | 
            +
                  result.should be_an_instance_of PG::Result
         | 
| 81 | 
            +
                  result[0]['number'].should eq "42"
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
              end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
              it "should timeout expire while executing query" do
         | 
| 86 | 
            +
                @client.query_timeout.should eq 0
         | 
| 87 | 
            +
                @client.query_timeout = 1.5
         | 
| 88 | 
            +
                @client.query_timeout.should eq 1.5
         | 
| 89 | 
            +
                start_time = Time.now
         | 
| 90 | 
            +
                expect {
         | 
| 91 | 
            +
                  @client.query('SELECT pg_sleep(2)')
         | 
| 92 | 
            +
                }.to raise_error(PG::Error, /query timeout expired/)
         | 
| 93 | 
            +
                (Time.now - start_time).should be < 2
         | 
| 94 | 
            +
                @client.query_timeout = 0
         | 
| 95 | 
            +
                @client.query_timeout.should eq 0
         | 
| 96 | 
            +
                @client.async_command_aborted.should be_true
         | 
| 97 | 
            +
                @client.query('BEGIN TRANSACTION') do |result|
         | 
| 98 | 
            +
                  result.should be_an_instance_of PG::Result
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
              end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
              it "should timeout not expire while executing query with partial results" do
         | 
| 103 | 
            +
                @client.query_timeout.should eq 0
         | 
| 104 | 
            +
                @client.query_timeout = 1.1
         | 
| 105 | 
            +
                @client.query_timeout.should eq 1.1
         | 
| 106 | 
            +
                start_time = Time.now
         | 
| 107 | 
            +
                @client.query(
         | 
| 108 | 
            +
                    'SELECT * from pg_class;' +
         | 
| 109 | 
            +
                    'SELECT pg_sleep(1);' +
         | 
| 110 | 
            +
                    'SELECT * from pg_class;' + 
         | 
| 111 | 
            +
                    'SELECT pg_sleep(1);' +
         | 
| 112 | 
            +
                    'SELECT 42 number') do |result|
         | 
| 113 | 
            +
                  (Time.now - start_time).should be > 2
         | 
| 114 | 
            +
                  result.should be_an_instance_of PG::Result
         | 
| 115 | 
            +
                  result[0]['number'].should eq "42"
         | 
| 116 | 
            +
                  @client.query_timeout = 0
         | 
| 117 | 
            +
                  @client.query_timeout.should eq 0
         | 
| 118 | 
            +
                  @client.async_command_aborted.should be_false
         | 
| 119 | 
            +
                end
         | 
| 120 | 
            +
              end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
              it "should timeout expire while executing query with partial results" do
         | 
| 123 | 
            +
                @client.query_timeout.should eq 0
         | 
| 124 | 
            +
                @client.query_timeout = 1.1
         | 
| 125 | 
            +
                @client.query_timeout.should eq 1.1
         | 
| 126 | 
            +
                start_time = Time.now
         | 
| 127 | 
            +
                expect {
         | 
| 128 | 
            +
                  @client.query(
         | 
| 129 | 
            +
                      'SELECT * from pg_class;' +
         | 
| 130 | 
            +
                      'SELECT pg_sleep(1);' +
         | 
| 131 | 
            +
                      'SELECT * from pg_class;' + 
         | 
| 132 | 
            +
                      'SELECT pg_sleep(2);' +
         | 
| 133 | 
            +
                      'SELECT 42 number')
         | 
| 134 | 
            +
                }.to raise_error(PG::Error, /query timeout expired/)
         | 
| 135 | 
            +
                (Time.now - start_time).should be > 2
         | 
| 136 | 
            +
                @client.query_timeout = 0
         | 
| 137 | 
            +
                @client.query_timeout.should eq 0
         | 
| 138 | 
            +
                @client.query('BEGIN TRANSACTION') do |result|
         | 
| 139 | 
            +
                  result.should be_an_instance_of PG::Result
         | 
| 140 | 
            +
                end
         | 
| 36 141 | 
             
              end
         | 
| 37 142 |  | 
| 38 143 | 
             
              around(:each) do |testcase|
         | 
| 39 | 
            -
                EM.synchrony  | 
| 144 | 
            +
                EM.synchrony do
         | 
| 145 | 
            +
                  begin
         | 
| 146 | 
            +
                    testcase.call
         | 
| 147 | 
            +
                  ensure
         | 
| 148 | 
            +
                    EM.stop
         | 
| 149 | 
            +
                  end
         | 
| 150 | 
            +
                end
         | 
| 40 151 | 
             
              end
         | 
| 41 152 |  | 
| 42 153 | 
             
              before(:all) do
         | 
| 43 154 | 
             
                @cdates = []
         | 
| 44 155 | 
             
                @values = Array(('AA'..'ZZ').each_with_index)
         | 
| 45 | 
            -
                @client =  | 
| 156 | 
            +
                @client = described_class.new
         | 
| 46 157 | 
             
                @client.query 'BEGIN TRANSACTION'
         | 
| 47 158 | 
             
              end
         | 
| 48 159 |  | 
| @@ -0,0 +1,118 @@ | |
| 1 | 
            +
            $:.unshift "lib"
         | 
| 2 | 
            +
            require 'date'
         | 
| 3 | 
            +
            require 'em-synchrony'
         | 
| 4 | 
            +
            require 'em-synchrony/pg'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            $pgserver_cmd_stop = %Q[sudo su - postgres -c 'pg_ctl stop -m fast']
         | 
| 7 | 
            +
            $pgserver_cmd_start = %Q[sudo su - postgres -c 'pg_ctl -l $PGDATA/postgres.log start -w']
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            shared_context 'em-synchrony-pg common' do
         | 
| 10 | 
            +
              around(:each) do |testcase|
         | 
| 11 | 
            +
                EM.synchrony do
         | 
| 12 | 
            +
                  testcase.call
         | 
| 13 | 
            +
                  EM.stop
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              after(:all) do
         | 
| 18 | 
            +
                @client.close
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            describe 'em-synchrony-pg default autoreconnect' do
         | 
| 23 | 
            +
              include_context 'em-synchrony-pg common'
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              it "should get database size using query" do
         | 
| 26 | 
            +
                @tested_proc.call
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              it "should get database size using query after server restart" do
         | 
| 30 | 
            +
                system($pgserver_cmd_stop).should be_true
         | 
| 31 | 
            +
                system($pgserver_cmd_start).should be_true
         | 
| 32 | 
            +
                @tested_proc.call
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              it "should not get database size using query after server shutdown" do
         | 
| 36 | 
            +
                system($pgserver_cmd_stop).should be_true
         | 
| 37 | 
            +
                expect {
         | 
| 38 | 
            +
                  @tested_proc.call
         | 
| 39 | 
            +
                }.to raise_error(PG::Error)
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              it "should get database size using query after server startup" do
         | 
| 43 | 
            +
                system($pgserver_cmd_start).should be_true
         | 
| 44 | 
            +
                @tested_proc.call
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              before(:all) do
         | 
| 48 | 
            +
                @tested_proc = proc do
         | 
| 49 | 
            +
                  @client.query('SELECT pg_database_size(current_database());') do |result|
         | 
| 50 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 51 | 
            +
                    result[0]['pg_database_size'].to_i.should be > 0
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
                @client = PG::EM::Client.new
         | 
| 55 | 
            +
                @client.set_notice_processor {|msg| puts "warning from pgsql: #{msg.to_s.chomp.inspect}"}
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
            end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            describe 'em-synchrony-pg autoreconnect with on_autoreconnect' do
         | 
| 60 | 
            +
              include_context 'em-synchrony-pg common'
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              it "should get database size using prepared statement" do
         | 
| 63 | 
            +
                @tested_proc.call
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              it "should get database size using prepared statement after server restart" do
         | 
| 67 | 
            +
                system($pgserver_cmd_stop).should be_true
         | 
| 68 | 
            +
                system($pgserver_cmd_start).should be_true
         | 
| 69 | 
            +
                @tested_proc.call
         | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
              before(:all) do
         | 
| 73 | 
            +
                @tested_proc = proc do
         | 
| 74 | 
            +
                  @client.exec_prepared('get_db_size') do |result|
         | 
| 75 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 76 | 
            +
                    result[0]['pg_database_size'].to_i.should be > 0
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
                on_autoreconnect = proc do |client, ex|
         | 
| 80 | 
            +
                  client.prepare('get_db_size', 'SELECT pg_database_size(current_database());')
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
                @client = PG::EM::Client.new(on_autoreconnect: on_autoreconnect)
         | 
| 83 | 
            +
                @client.set_notice_processor {|msg| puts "warning from pgsql: #{msg.to_s.chomp.inspect}"}
         | 
| 84 | 
            +
                on_autoreconnect.call @client
         | 
| 85 | 
            +
              end
         | 
| 86 | 
            +
            end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
            describe 'em-synchrony-pg with autoreconnect disabled' do
         | 
| 89 | 
            +
              include_context 'em-synchrony-pg common'
         | 
| 90 | 
            +
             | 
| 91 | 
            +
              it "should get database size using query" do
         | 
| 92 | 
            +
                @tested_proc.call
         | 
| 93 | 
            +
              end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
              it "should not get database size using query after server restart" do
         | 
| 96 | 
            +
                system($pgserver_cmd_stop).should be_true
         | 
| 97 | 
            +
                system($pgserver_cmd_start).should be_true
         | 
| 98 | 
            +
                expect {
         | 
| 99 | 
            +
                  @tested_proc.call
         | 
| 100 | 
            +
                }.to raise_error(PG::Error)
         | 
| 101 | 
            +
              end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
              it "should get database size using query after manual connection reset" do
         | 
| 104 | 
            +
                @client.reset
         | 
| 105 | 
            +
                @tested_proc.call
         | 
| 106 | 
            +
              end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
              before(:all) do
         | 
| 109 | 
            +
                @tested_proc = proc do
         | 
| 110 | 
            +
                  @client.query('SELECT pg_database_size(current_database());') do |result|
         | 
| 111 | 
            +
                    result.should be_an_instance_of PG::Result
         | 
| 112 | 
            +
                    result[0]['pg_database_size'].to_i.should be > 0
         | 
| 113 | 
            +
                  end
         | 
| 114 | 
            +
                end
         | 
| 115 | 
            +
                @client = PG::EM::Client.new(async_autoreconnect: false)
         | 
| 116 | 
            +
                @client.set_notice_processor {|msg| puts "warning from pgsql: #{msg.to_s.chomp.inspect}"}
         | 
| 117 | 
            +
              end
         | 
| 118 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -2,7 +2,7 @@ | |
| 2 2 | 
             
            name: em-pg-client
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 4 | 
             
              prerelease: 6
         | 
| 5 | 
            -
              version: 0.2.0.pre. | 
| 5 | 
            +
              version: 0.2.0.pre.3
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors: 
         | 
| 8 8 | 
             
            - Rafal Michalski
         | 
| @@ -10,7 +10,7 @@ autorequire: | |
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 12 |  | 
| 13 | 
            -
            date: 2012- | 
| 13 | 
            +
            date: 2012-05-02 00:00:00 Z
         | 
| 14 14 | 
             
            dependencies: 
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| 16 16 | 
             
              name: pg
         | 
| @@ -85,9 +85,12 @@ files: | |
| 85 85 | 
             
            - em-pg-client.gemspec
         | 
| 86 86 | 
             
            - lib/em-synchrony/pg.rb
         | 
| 87 87 | 
             
            - lib/pg/em.rb
         | 
| 88 | 
            +
            - spec/em_client_autoreconnect.rb
         | 
| 89 | 
            +
            - spec/em_client_common.rb
         | 
| 88 90 | 
             
            - spec/em_devel_client.rb
         | 
| 89 91 | 
             
            - spec/em_release_client.rb
         | 
| 90 92 | 
             
            - spec/em_synchrony_client.rb
         | 
| 93 | 
            +
            - spec/em_synchrony_client_autoreconnect.rb
         | 
| 91 94 | 
             
            homepage: http://github.com/royaltm/ruby-em-pg-client
         | 
| 92 95 | 
             
            licenses: []
         | 
| 93 96 |  | 
| @@ -121,4 +124,7 @@ summary: EventMachine PostgreSQL client | |
| 121 124 | 
             
            test_files: 
         | 
| 122 125 | 
             
            - spec/em_synchrony_client.rb
         | 
| 123 126 | 
             
            - spec/em_devel_client.rb
         | 
| 127 | 
            +
            - spec/em_client_common.rb
         | 
| 124 128 | 
             
            - spec/em_release_client.rb
         | 
| 129 | 
            +
            - spec/em_synchrony_client_autoreconnect.rb
         | 
| 130 | 
            +
            - spec/em_client_autoreconnect.rb
         |