em-pg-client 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,8 @@
1
+ 0.2.1
2
+ - support for pg >= 0.14 native PG::Result#check
3
+ - support for pg >= 0.14 native PG::Connection#set_default_encoding
4
+ - fix: connection option Hash argument was modified by Client.new and Client.async_connect
5
+
1
6
  0.2.0
2
7
  - disabled async_autoreconnect by default unless on_autoreconnect is set
3
8
  - async_connect sets #internal_encoding to Encoding.default_internal
@@ -43,8 +43,8 @@ RDBMS. It is based on ruby-pg[https://bitbucket.org/ged/ruby-pg].
43
43
 
44
44
  == REQUIREMENTS
45
45
 
46
- * ruby >= 1.9 (tested: 1.9.3-p194, 1.9.2-p320, 1.9.2-p280, 1.9.1-p378)
47
- * https://bitbucket.org/ged/ruby-pg >= 0.13
46
+ * ruby >= 1.9 (tested: 1.9.3-p194, 1.9.2-p320, 1.9.1-p378)
47
+ * https://bitbucket.org/ged/ruby-pg >= 0.13.2 (>= 0.14 recommended)
48
48
  * PostgreSQL[http://www.postgresql.org/ftp/source/] RDBMS >= 8.3
49
49
  * http://rubyeventmachine.com >= 0.12.10
50
50
  * (optional) EM-Synchrony[https://github.com/igrigorik/em-synchrony]
@@ -56,9 +56,9 @@ RDBMS. It is based on ruby-pg[https://bitbucket.org/ged/ruby-pg].
56
56
  ==== Gemfile
57
57
 
58
58
  # eventmachine
59
- gem "em-pg-client", "~> 0.2.0", :require => 'pg/em'
59
+ gem "em-pg-client", "~> 0.2.1", :require => 'pg/em'
60
60
  # em-synchrony
61
- gem "em-pg-client", "~> 0.2.0", :require => ['pg/em', 'em-synchrony/pg']
61
+ gem "em-pg-client", "~> 0.2.1", :require => ['pg/em', 'em-synchrony/pg']
62
62
 
63
63
  ==== Github
64
64
 
data/Rakefile CHANGED
@@ -8,8 +8,10 @@ desc "Run spec tests"
8
8
  task :test, [:which] do |t, args|
9
9
  args.with_defaults(:which => 'safe')
10
10
 
11
- env_unix_socket = {'PGDATABASE' => 'test', 'PGHOST' => '/tmp'}
12
- env_tcpip = {'PGDATABASE' => 'test', 'PGHOST' => 'localhost'}
11
+ env_common = {'PGDATABASE' => 'test'}
12
+ env_pg_013 = {'EM_PG_CLIENT_TEST_PG_VERSION' => '= 0.13.2'}
13
+ env_unix_socket = env_common.merge('PGHOST' => '/tmp')
14
+ env_tcpip = env_common.merge('PGHOST' => 'localhost')
13
15
 
14
16
  puts "WARNING: The test needs to be run with an available local PostgreSQL server"
15
17
 
@@ -21,10 +23,13 @@ task :test, [:which] do |t, args|
21
23
  ].each do |spec|
22
24
  sh env_unix_socket, "rspec #{spec}"
23
25
  sh env_tcpip, "rspec #{spec}"
26
+ sh env_pg_013.merge(env_unix_socket), "rspec #{spec}"
27
+ sh env_pg_013.merge(env_tcpip), "rspec #{spec}"
24
28
  end
25
29
  end
26
30
 
27
31
  if %w[all unsafe dangerous autoreconnect].include? args[:which]
32
+ raise "Set PGDATA environment variable before running the autoreconnect tests." unless ENV['PGDATA']
28
33
  %w[
29
34
  spec/em_client_autoreconnect.rb
30
35
  spec/em_synchrony_client_autoreconnect.rb
@@ -2,7 +2,7 @@ $:.unshift "lib"
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "em-pg-client"
5
- s.version = "0.2.0"
5
+ s.version = "0.2.1"
6
6
  s.required_ruby_version = ">= 1.9.1"
7
7
  s.date = "#{Time.now.strftime("%Y-%m-%d")}"
8
8
  s.summary = "EventMachine PostgreSQL client"
@@ -13,34 +13,6 @@ end
13
13
 
14
14
  module PG
15
15
 
16
- class Result
17
- class << self
18
- unless method_defined? :check_result
19
- # pg_check_result is internal ext function. I wish it was rubified.
20
- # https://bitbucket.org/ged/ruby-pg/issue/123/rubify-pg_check_result
21
- def check_result(connection, result)
22
- if result.nil?
23
- if (error_message = connection.error_message)
24
- error = PG::Error.new(error_message)
25
- end
26
- else
27
- case result.result_status
28
- when PG::PGRES_BAD_RESPONSE,
29
- PG::PGRES_FATAL_ERROR,
30
- PG::PGRES_NONFATAL_ERROR
31
- error = PG::Error.new(result.error_message)
32
- error.instance_variable_set('@result', result)
33
- end
34
- end
35
- if error
36
- error.instance_variable_set('@connection', connection)
37
- raise error
38
- end
39
- end
40
- end
41
- end
42
- end
43
-
44
16
  module EM
45
17
  class FeaturedDeferrable < ::EM::DefaultDeferrable
46
18
  def initialize(&blk)
@@ -215,8 +187,12 @@ module PG
215
187
  @client.consume_input
216
188
  until @client.is_busy
217
189
  if (single_result = @client.get_result).nil?
218
- result = @last_result
219
- Result.check_result(@client, result)
190
+ if (result = @last_result).nil?
191
+ error = PG::Error.new(@client.error_message)
192
+ error.instance_variable_set(:@connection, @client)
193
+ raise error
194
+ end
195
+ result.check
220
196
  detach
221
197
  @timer.cancel if @timer
222
198
  break
@@ -283,7 +259,7 @@ module PG
283
259
  when PG::PGRES_POLLING_OK, PG::PGRES_POLLING_FAILED
284
260
  @timer.cancel if @timer
285
261
  detach
286
- success = @deferrable.protect_and_succeed do
262
+ @deferrable.protect_and_succeed do
287
263
  unless @client.status == PG::CONNECTION_OK
288
264
  begin
289
265
  raise PG::Error, @client.error_message
@@ -292,20 +268,14 @@ module PG
292
268
  end
293
269
  end
294
270
  # mimic blocking connect behavior
295
- unless Encoding.default_internal.nil? || reconnecting?
296
- begin
297
- @client.internal_encoding = Encoding.default_internal
298
- rescue EncodingError
299
- warn "warning: Failed to set the default_internal encoding to #{Encoding.default_internal}: '#{@client.error_message}'"
300
- end
301
- end
271
+ @client.set_default_encoding unless reconnecting?
302
272
  @client
303
273
  end
304
274
  end
305
275
  end
306
276
  end
307
277
 
308
- def self.parse_async_args(*args)
278
+ def self.parse_async_args(args)
309
279
  async_args = {
310
280
  :@async_autoreconnect => nil,
311
281
  :@connect_timeout => 0,
@@ -314,7 +284,7 @@ module PG
314
284
  :@async_command_aborted => false,
315
285
  }
316
286
  if args.last.is_a? Hash
317
- args.last.reject! do |key, value|
287
+ args[-1] = args.last.reject do |key, value|
318
288
  case key.to_s
319
289
  when 'async_autoreconnect'
320
290
  async_args[:@async_autoreconnect] = !!value
@@ -353,7 +323,7 @@ module PG
353
323
  # +client_encoding+ *will* be set for you according to Encoding.default_internal.
354
324
  def self.async_connect(*args, &blk)
355
325
  df = PG::EM::FeaturedDeferrable.new(&blk)
356
- async_args = parse_async_args(*args)
326
+ async_args = parse_async_args(args)
357
327
  conn = df.protect { connect_start(*args) }
358
328
  if conn
359
329
  async_args.each {|k, v| conn.instance_variable_set(k, v) }
@@ -393,7 +363,7 @@ module PG
393
363
  # +em-synchrony+ version *will* do set +client_encoding+ for you according to
394
364
  # Encoding.default_internal.
395
365
  def initialize(*args)
396
- Client.parse_async_args(*args).each {|k, v| self.instance_variable_set(k, v) }
366
+ Client.parse_async_args(args).each {|k, v| self.instance_variable_set(k, v) }
397
367
  super(*args)
398
368
  end
399
369
 
@@ -476,6 +446,48 @@ module PG
476
446
 
477
447
  alias_method :query, :exec
478
448
  alias_method :async_query, :async_exec
449
+
450
+ # support for pg < 0.14.0
451
+ unless method_defined? :set_default_encoding
452
+ def set_default_encoding
453
+ unless Encoding.default_internal.nil?
454
+ self.internal_encoding = Encoding.default_internal
455
+ end
456
+ rescue EncodingError
457
+ warn "warning: Failed to set the default_internal encoding to #{Encoding.default_internal}: '#{self.error_message}'"
458
+ Encoding.default_internal
459
+ end
460
+ end
461
+
462
+ end
463
+ end
464
+
465
+ # support for pg < 0.14.0
466
+ unless Result.method_defined? :check
467
+ class Result
468
+ def check
469
+ case result_status
470
+ when PG::PGRES_BAD_RESPONSE,
471
+ PG::PGRES_FATAL_ERROR,
472
+ PG::PGRES_NONFATAL_ERROR
473
+ error = PG::Error.new(error_message)
474
+ error.instance_variable_set(:@result, self)
475
+ error.instance_variable_set(:@connection, @connection)
476
+ raise error
477
+ end
478
+ end
479
+ alias_method :check_result, :check
480
+ end
481
+
482
+ module EM
483
+ class Client < PG::Connection
484
+ def get_result(&blk)
485
+ result = super(&blk)
486
+ result.instance_variable_set(:@connection, self) unless block_given?
487
+ result
488
+ end
489
+ end
479
490
  end
480
491
  end
492
+
481
493
  end
@@ -19,6 +19,14 @@ end
19
19
  describe 'em-pg default autoreconnect' do
20
20
  include_context 'em-pg common'
21
21
 
22
+ it "should not have modified argument Hash" do
23
+ begin
24
+ @options.should eq(async_autoreconnect: true)
25
+ ensure
26
+ EM.stop
27
+ end
28
+ end
29
+
22
30
  it "should get database size using query" do
23
31
  @tested_proc.call
24
32
  end
@@ -50,7 +58,8 @@ describe 'em-pg default autoreconnect' do
50
58
  EM.stop
51
59
  end.should be_a_kind_of ::EM::DefaultDeferrable
52
60
  end
53
- @client = PG::EM::Client.new(async_autoreconnect: true)
61
+ @options = {async_autoreconnect: true}
62
+ @client = PG::EM::Client.new(@options)
54
63
  @client.set_notice_processor {|msg| puts "warning from pgsql: #{msg.to_s.chomp.inspect}"}
55
64
  end
56
65
  end
@@ -58,6 +67,14 @@ end
58
67
  describe 'em-pg autoreconnect with on_autoreconnect' do
59
68
  include_context 'em-pg common'
60
69
 
70
+ it "should not have modified argument Hash" do
71
+ begin
72
+ @options.should eq(on_autoreconnect: @on_autoreconnect)
73
+ ensure
74
+ EM.stop
75
+ end
76
+ end
77
+
61
78
  it "should get database size using prepared statement"do
62
79
  @tested_proc.call
63
80
  end
@@ -76,12 +93,13 @@ describe 'em-pg autoreconnect with on_autoreconnect' do
76
93
  EM.stop
77
94
  end.should be_a_kind_of ::EM::DefaultDeferrable
78
95
  end
79
- on_autoreconnect = proc do |client, ex|
96
+ @on_autoreconnect = proc do |client, ex|
80
97
  df = client.prepare('get_db_size', 'SELECT pg_database_size(current_database());')
81
98
  df.should be_a_kind_of ::EM::DefaultDeferrable
82
99
  df
83
100
  end
84
- @client = PG::EM::Client.new(on_autoreconnect: on_autoreconnect)
101
+ @options = {on_autoreconnect: @on_autoreconnect}
102
+ @client = PG::EM::Client.new(@options)
85
103
  @client.set_notice_processor {|msg| puts "warning from pgsql: #{msg.to_s.chomp.inspect}"}
86
104
  @client.prepare('get_db_size', 'SELECT pg_database_size(current_database());')
87
105
  end
@@ -68,7 +68,7 @@ shared_context 'em-pg common before' do
68
68
  @client.close
69
69
  end
70
70
 
71
- it "should be a client" do
71
+ it "should be a client #{PG::VERSION}" do
72
72
  ensure_em_stop do
73
73
  @client.should be_an_instance_of described_class
74
74
  end
@@ -90,21 +90,27 @@ shared_context 'em-pg common before' do
90
90
  it "should set async_autoreconnect according to on_autoreconnect" do
91
91
  ensure_em_stop do
92
92
  on_autoreconnect = proc {|c, e| false }
93
- async_args = described_class.parse_async_args
93
+ async_args = described_class.parse_async_args([])
94
94
  async_args.should be_an_instance_of Hash
95
95
  async_args[:@on_autoreconnect].should be_nil
96
96
  async_args[:@async_autoreconnect].should be_false
97
- async_args = described_class.parse_async_args(on_autoreconnect: on_autoreconnect)
97
+ args = [on_autoreconnect: on_autoreconnect]
98
+ async_args = described_class.parse_async_args(args)
99
+ args.should eq [{}]
98
100
  async_args.should be_an_instance_of Hash
99
101
  async_args[:@on_autoreconnect].should be on_autoreconnect
100
102
  async_args[:@async_autoreconnect].should be_true
101
- async_args = described_class.parse_async_args(async_autoreconnect: false,
102
- on_autoreconnect: on_autoreconnect)
103
+ args = [async_autoreconnect: false,
104
+ on_autoreconnect: on_autoreconnect]
105
+ async_args = described_class.parse_async_args(args)
106
+ args.should eq [{}]
103
107
  async_args.should be_an_instance_of Hash
104
108
  async_args[:@on_autoreconnect].should be on_autoreconnect
105
109
  async_args[:@async_autoreconnect].should be_false
106
- async_args = described_class.parse_async_args(on_autoreconnect: on_autoreconnect,
107
- async_autoreconnect: false)
110
+ args = [on_autoreconnect: on_autoreconnect,
111
+ async_autoreconnect: false]
112
+ async_args = described_class.parse_async_args(args)
113
+ args.should eq [{}]
108
114
  async_args.should be_an_instance_of Hash
109
115
  async_args[:@on_autoreconnect].should be on_autoreconnect
110
116
  async_args[:@async_autoreconnect].should be_false
@@ -1,5 +1,6 @@
1
1
  $:.unshift "lib"
2
2
  gem 'eventmachine', '>= 1.0.0.beta.1'
3
+ gem 'pg', ENV['EM_PG_CLIENT_TEST_PG_VERSION']
3
4
  require 'date'
4
5
  require 'eventmachine'
5
6
  require 'pg/em'
@@ -1,5 +1,6 @@
1
1
  $:.unshift "lib"
2
2
  gem 'eventmachine', '= 0.12.10'
3
+ gem 'pg', ENV['EM_PG_CLIENT_TEST_PG_VERSION']
3
4
  require 'date'
4
5
  require 'eventmachine'
5
6
  require 'pg/em'
@@ -1,11 +1,12 @@
1
1
  $:.unshift "lib"
2
+ gem 'pg', ENV['EM_PG_CLIENT_TEST_PG_VERSION']
2
3
  require 'date'
3
4
  require 'em-synchrony'
4
5
  require 'em-synchrony/pg'
5
6
 
6
7
  describe PG::EM::Client do
7
8
 
8
- it "should be client" do
9
+ it "should be client #{PG::VERSION}" do
9
10
  @client.should be_an_instance_of described_class
10
11
  end
11
12
 
@@ -22,6 +22,10 @@ end
22
22
  describe 'em-synchrony-pg default autoreconnect' do
23
23
  include_context 'em-synchrony-pg common'
24
24
 
25
+ it "should not have modified argument Hash" do
26
+ @options.should eq(async_autoreconnect: true)
27
+ end
28
+
25
29
  it "should get database size using query" do
26
30
  @tested_proc.call
27
31
  end
@@ -51,7 +55,8 @@ describe 'em-synchrony-pg default autoreconnect' do
51
55
  result[0]['pg_database_size'].to_i.should be > 0
52
56
  end
53
57
  end
54
- @client = PG::EM::Client.new(async_autoreconnect: true)
58
+ @options = {async_autoreconnect: true}
59
+ @client = PG::EM::Client.new(@options)
55
60
  @client.set_notice_processor {|msg| puts "warning from pgsql: #{msg.to_s.chomp.inspect}"}
56
61
  end
57
62
  end
@@ -59,6 +64,10 @@ end
59
64
  describe 'em-synchrony-pg autoreconnect with on_autoreconnect' do
60
65
  include_context 'em-synchrony-pg common'
61
66
 
67
+ it "should not have modified argument Hash" do
68
+ @options.should eq(on_autoreconnect: @on_autoreconnect)
69
+ end
70
+
62
71
  it "should get database size using prepared statement" do
63
72
  @tested_proc.call
64
73
  end
@@ -76,12 +85,13 @@ describe 'em-synchrony-pg autoreconnect with on_autoreconnect' do
76
85
  result[0]['pg_database_size'].to_i.should be > 0
77
86
  end
78
87
  end
79
- on_autoreconnect = proc do |client, ex|
88
+ @on_autoreconnect = proc do |client, ex|
80
89
  client.prepare('get_db_size', 'SELECT pg_database_size(current_database());')
81
90
  end
82
- @client = PG::EM::Client.new(on_autoreconnect: on_autoreconnect)
91
+ @options = {on_autoreconnect: @on_autoreconnect}
92
+ @client = PG::EM::Client.new(@options)
83
93
  @client.set_notice_processor {|msg| puts "warning from pgsql: #{msg.to_s.chomp.inspect}"}
84
- on_autoreconnect.call @client
94
+ @on_autoreconnect.call @client
85
95
  end
86
96
  end
87
97
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-pg-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-08 00:00:00.000000000 Z
12
+ date: 2012-09-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: pg
16
- requirement: !ruby/object:Gem::Requirement
16
+ requirement: &244130120 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,15 +21,10 @@ dependencies:
21
21
  version: 0.13.2
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: 0.13.2
24
+ version_requirements: *244130120
30
25
  - !ruby/object:Gem::Dependency
31
26
  name: eventmachine
32
- requirement: !ruby/object:Gem::Requirement
27
+ requirement: &244129580 !ruby/object:Gem::Requirement
33
28
  none: false
34
29
  requirements:
35
30
  - - ! '>='
@@ -37,15 +32,10 @@ dependencies:
37
32
  version: 0.12.10
38
33
  type: :runtime
39
34
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: 0.12.10
35
+ version_requirements: *244129580
46
36
  - !ruby/object:Gem::Dependency
47
37
  name: rspec
48
- requirement: !ruby/object:Gem::Requirement
38
+ requirement: &244128480 !ruby/object:Gem::Requirement
49
39
  none: false
50
40
  requirements:
51
41
  - - ~>
@@ -53,15 +43,10 @@ dependencies:
53
43
  version: 2.8.0
54
44
  type: :development
55
45
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: 2.8.0
46
+ version_requirements: *244128480
62
47
  - !ruby/object:Gem::Dependency
63
48
  name: eventmachine
64
- requirement: !ruby/object:Gem::Requirement
49
+ requirement: &244127700 !ruby/object:Gem::Requirement
65
50
  none: false
66
51
  requirements:
67
52
  - - ! '>='
@@ -69,15 +54,10 @@ dependencies:
69
54
  version: 1.0.0.beta.1
70
55
  type: :development
71
56
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: 1.0.0.beta.1
57
+ version_requirements: *244127700
78
58
  - !ruby/object:Gem::Dependency
79
59
  name: em-synchrony
80
- requirement: !ruby/object:Gem::Requirement
60
+ requirement: &244126900 !ruby/object:Gem::Requirement
81
61
  none: false
82
62
  requirements:
83
63
  - - ~>
@@ -85,12 +65,7 @@ dependencies:
85
65
  version: 1.0.0
86
66
  type: :development
87
67
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ~>
92
- - !ruby/object:Gem::Version
93
- version: 1.0.0
68
+ version_requirements: *244126900
94
69
  description: PostgreSQL asynchronous EventMachine client, based on pg interface (PG::Connection)
95
70
  email: rafal@yeondir.com
96
71
  executables: []
@@ -138,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
113
  requirements:
139
114
  - PostgreSQL server
140
115
  rubyforge_project:
141
- rubygems_version: 1.8.23
116
+ rubygems_version: 1.8.17
142
117
  signing_key:
143
118
  specification_version: 3
144
119
  summary: EventMachine PostgreSQL client