em-pg-client 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY.rdoc ADDED
@@ -0,0 +1,9 @@
1
+ 0.1.1
2
+ - added on_reconnect callback
3
+ - docs updated
4
+ - added development dependency for eventmachine >= 1.0.0.beta.1
5
+ - added separate client specs for eventmachine = 0.12.10
6
+ - added error checking to eventmachine specs
7
+
8
+ 0.1.0
9
+ - first release
data/README.rdoc CHANGED
@@ -1,17 +1,17 @@
1
1
  = em-pg-client
2
2
 
3
- Author:: Rafał Michalski (mailto:royaltm75@gmail.com)
3
+ Author:: Rafał Michalski (mailto:rafal@yeondir.com)
4
4
 
5
5
  * http://github.com/royaltm/ruby-em-pg-client
6
6
 
7
7
  == DESCRIPTION
8
8
 
9
9
  *em-pg-client* is a PostgreSQL EventMachine client wrapper for Ruby
10
- based on (ruby-pg)[https://bitbucket.org/ged/ruby-pg]
10
+ based on ruby-pg[https://bitbucket.org/ged/ruby-pg]
11
11
 
12
12
  == FEATURES
13
13
 
14
- * minimal changes to PG::Conncet API
14
+ * minimal changes to PG::Connection API
15
15
  * auto reconnects on socket connection loss (like server restarts)
16
16
  * true non-blocking asynchronous processing
17
17
  * EM-Synchrony[https://github.com/igrigorik/em-synchrony] support
@@ -49,7 +49,7 @@ I've found at least 3 other implementations of EM postgres client:
49
49
  and (except the bundled one which uses no longer maintained postgres-pr library)
50
50
  all of them have similiar flaws:
51
51
 
52
- * 2 of them are designed to support some ORM only (ActiveRecord or Sequel)
52
+ * 2 of them are designed to support some ORM (ActiveRecord or Sequel)
53
53
  so they are EM-Synchrony only,
54
54
  * non-standard API method names,
55
55
  * no (nonexistent or non-working) autoreconnect implementation,
@@ -81,14 +81,14 @@ The greetz go to:
81
81
  # no async
82
82
  pg = PG::EM::Client.new dbname: 'test'
83
83
  pq.query('select * from foo') do |result|
84
- puts result
84
+ puts Array(result).inspect
85
85
  end
86
86
 
87
87
  # asynchronous
88
88
  EM.run do
89
89
  pq.query('select * from foo') do |result|
90
90
  raise result if result.is_a? ::Exception
91
- puts result
91
+ puts Array(result).inspect
92
92
  EM.stop
93
93
  end
94
94
  puts "sent"
@@ -98,11 +98,10 @@ The greetz go to:
98
98
 
99
99
  EM.run do
100
100
  pg = PG::EM::Client.new dbname: 'test'
101
-
102
- try_query = lambda |&blk| do
103
- pq.query('select * from foo') do |result|
101
+ try_query = lambda do |&blk|
102
+ pg.query('select * from foo') do |result|
104
103
  raise result if result.is_a? ::Exception
105
- puts result
104
+ puts Array(result).inspect
106
105
  blk.call
107
106
  end
108
107
  end
@@ -124,6 +123,37 @@ or
124
123
  pg = PG::EM::Client.new dbname: 'test',
125
124
  async_autoreconnect: false
126
125
 
126
+ It's also possible to define +on_reconnect+ callback to be invoked
127
+ while the connection has been reset. It's called just before the send query
128
+ command is executed:
129
+
130
+ EM.run do
131
+ pg = PG::EM::Client.new dbname: 'test'
132
+ pg.prepare('bar', 'select * from foo order by cdate desc') do
133
+ pg.on_reconnect = proc { |c, e|
134
+ c.prepare('bar', 'select * from foo order by cdate desc')
135
+ }
136
+ try_query = lambda do |&blk|
137
+ pg.exec_prepared('bar') do |result|
138
+ raise result if result.is_a? ::Exception
139
+ puts Array(result).inspect
140
+ blk.call
141
+ end
142
+ end
143
+ try_query.call {
144
+ system 'pg_ctl stop -m fast'
145
+ system 'pg_ctl start -w'
146
+ EM.add_timer(1) do
147
+ try_query.call { EM.stop }
148
+ end
149
+ }
150
+ end
151
+ end
152
+
153
+ As you can see it's possible to send async query from inside on_reconnect
154
+ proc. However you have to pass +Deferrable+ from the async callback to the
155
+ caller. See +#on_reconnect+ docs for details.
156
+
127
157
  === TRUE ASYNC
128
158
 
129
159
  EM.run do
@@ -147,7 +177,7 @@ or
147
177
  EM.synchrony do
148
178
  pg = PG::EM::Client.new dbname: 'test'
149
179
  pg.query('select * from foo') do |result|
150
- puts result
180
+ puts Array(result).inspect
151
181
  end
152
182
  EM.stop
153
183
  end
@@ -198,6 +228,31 @@ or
198
228
  EM.stop
199
229
  end
200
230
 
231
+ ==== Async reconnect with on_reconnect callback
232
+
233
+ EM.synchrony do
234
+ pg = EM::Synchrony::ConnectionPool.new(size: 5) do
235
+ p = PG::EM::Client.new dbname: 'test'
236
+ p.on_reconnect = proc do |c, e|
237
+ c.prepare('bar', 'select * from foo order by cdate desc')
238
+ end
239
+ p.on_reconnect.call p
240
+ p
241
+ end
242
+ try_query = lambda do
243
+ pg.exec_prepared('bar') do |result|
244
+ raise result if result.is_a? ::Exception
245
+ puts Array(result).inspect
246
+ end
247
+ end
248
+ try_query.call
249
+ system 'pg_ctl stop -m fast'
250
+ system 'pg_ctl start -w'
251
+ EM::Synchrony.sleep(1)
252
+ try_query.call
253
+ EM.stop
254
+ end
255
+
201
256
  == LICENCE
202
257
 
203
258
  The MIT License - Copyright (c) 2012 Rafał Michalski
data/Rakefile CHANGED
@@ -7,7 +7,8 @@ $gem_name = "em-pg-client"
7
7
  desc "Run tests"
8
8
  task :test do
9
9
  puts "WARNING: The test needs to be run with an available local PostgreSQL server"
10
- sh "rspec spec/em_client.rb"
10
+ sh "rspec spec/em_release_client.rb"
11
+ sh "rspec spec/em_devel_client.rb"
11
12
  sh "rspec spec/em_synchrony_client.rb"
12
13
  end
13
14
 
data/em-pg-client.gemspec CHANGED
@@ -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.1.0"
5
+ s.version = "0.1.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"
@@ -21,5 +21,6 @@ Gem::Specification.new do |s|
21
21
  s.add_runtime_dependency "pg", ">= 0.13.2"
22
22
  s.add_runtime_dependency "eventmachine", ">= 0.12.10"
23
23
  s.add_development_dependency "rspec", "~> 2.8.0"
24
+ s.add_development_dependency "eventmachine", ">= 1.0.0.beta.1"
24
25
  s.add_development_dependency "em-synchrony", "~> 1.0.0"
25
26
  end
data/lib/pg/em.rb CHANGED
@@ -1,48 +1,75 @@
1
1
  require 'pg'
2
2
  module PG
3
3
  module EM
4
+ # == PostgreSQL EventMachine client
5
+ #
6
+ # Author:: Rafal Michalski (mailto:royaltm75@gmail.com)
7
+ # Licence:: MIT License
8
+ #
9
+ #
10
+ # PG::EM::Client is a wrapper for PG::Connection which (re)defines methods:
11
+ #
12
+ # - +async_exec+ (alias: +async_query+)
13
+ # - +async_prepare+
14
+ # - +async_exec_prepared+
15
+ #
16
+ # and following:
17
+ #
18
+ # - +exec+ (alias: +query+)
19
+ # - +exec_prepared+
20
+ # - +prepare+
21
+ #
22
+ # which autodetects if EventMachine is running and uses appropriate
23
+ # (async or sync) method version.
24
+ #
25
+ # Async methods might try to reset connection on connection error,
26
+ # you won't even notice that (except for warning message from PG).
27
+ #
28
+ # To disable such behavior set:
29
+ # client.async_autoreconnect = false
30
+ #
31
+ # or pass as new() hash argument:
32
+ # PG::EM::Client.new database: 'bar', async_autoreconnect: false
33
+ #
34
+ # Otherwise nothing changes in PG::Connect API.
35
+ # See PG::Connect docs for arguments to above methods.
36
+ #
37
+ # *Warning:*
38
+ #
39
+ # +async_exec_prepared+ after +async_prepare+ should only be invoked on
40
+ # the *same* connection.
41
+ # If you are using connection pool, make sure to acquire single connection first.
42
+ #
4
43
  class Client < PG::Connection
5
- # == PostgreSQL EventMachine client
6
- #
7
- # Author:: Rafal Michalski (mailto:royaltm75@gmail.com)
8
- # Licence:: MIT License
9
- #
10
- #
11
- # PG::EM::Client is a wrapper for PG::Connection which (re)defines methods:
12
- #
13
- # - +async_exec+ (alias: +async_query+)
14
- # - +async_prepare+
15
- # - +async_exec_prepared+
16
- #
17
- # and following:
18
- #
19
- # - +exec+ (alias: +query+)
20
- # - +exec_prepared+
21
- # - +prepare+
22
- #
23
- # which autodetects if EventMachine is running and uses appropriate
24
- # (async or sync) method version.
25
- #
26
- # Async methods might try to reset connection on connection error,
27
- # you won't even notice that (except for warning message from PG).
28
- #
29
- # To disable such behavior set:
30
- # client.async_autoreconnect = false
44
+
45
+ attr_accessor :async_autoreconnect
46
+
47
+ # +on_reconnect+ is a user defined Proc that is called after a connection
48
+ # with the server has been re-established.
49
+ # It's invoked with +connection+ as first argument and original
50
+ # +exception+ that caused the reconnecting process as second argument.
31
51
  #
32
- # or pass as new() hash argument:
33
- # PG::EM::Client.new database: 'bar', async_autoreconnect: false
52
+ # Certain rules should apply to on_reconnect proc:
34
53
  #
35
- # Otherwise nothing changes in PG::Connect API.
36
- # See PG::Connect docs for arguments to above methods.
54
+ # - +async_autoreconnect+ is switched off (do not try to change it from
55
+ # inside on_reconnect proc).
56
+ # - If proc returns +false+ (explicitly, +nil+ is ignored)
57
+ # the original +exception+ is raised and the send query command is
58
+ # not invoked at all.
59
+ # - If return value responds to +callback+ and +errback+ methods
60
+ # (like +Deferrable+), the send query command will be bound to this
61
+ # deferrable's success callback. Otherwise the send query command is called
62
+ # immediately after on_reconnect proc is executed.
63
+ # - Other return values are ignored.
37
64
  #
38
- # *Warning:*
65
+ # You may pass this proc as +:on_reconnect+ option to PG::EM::Client.new.
39
66
  #
40
- # +async_exec_prepared+ after +async_prepare+ should only be invoked on
41
- # the *same* connection.
42
- # If you are using connection pool, make sure to acquire single connection first.
67
+ # Example:
68
+ # pg.on_reconnect = proc do |conn, ex|
69
+ # conn.prepare("birds_by_name", "select id, name from animals order by name where species=$1", ['birds'])
70
+ # end
43
71
  #
44
-
45
- attr_accessor :async_autoreconnect
72
+ attr_accessor :on_reconnect
46
73
 
47
74
  module Watcher
48
75
  def initialize(client, deferrable)
@@ -66,11 +93,16 @@ module PG
66
93
 
67
94
  def initialize(*args)
68
95
  @async_autoreconnect = true
96
+ @on_reconnect = nil
69
97
  if args.last.is_a? Hash
70
98
  args.last.reject! do |key, value|
71
- if key.to_s == 'async_autoreconnect'
99
+ case key.to_s
100
+ when 'async_autoreconnect'
72
101
  @async_autoreconnect = !!value
73
102
  true
103
+ when 'on_reconnect'
104
+ @on_reconnect = value if value.respond_to? :call
105
+ true
74
106
  end
75
107
  end
76
108
  end
@@ -85,22 +117,41 @@ module PG
85
117
 
86
118
  class_eval <<-EOD
87
119
  def async_#{name}(*args, &blk)
120
+ df = ::EM::DefaultDeferrable.new
121
+ if block_given?
122
+ df.callback(&blk)
123
+ df.errback(&blk)
124
+ end
88
125
  begin
89
126
  #{send_name}(*args)
90
127
  rescue PG::Error => e
91
128
  if self.status != PG::CONNECTION_OK && async_autoreconnect
92
129
  reset
93
- #{send_name}(*args)
130
+ if on_reconnect
131
+ begin
132
+ self.async_autoreconnect = false
133
+ returned_df = on_reconnect.call(self, e)
134
+ raise e if returned_df == false
135
+ if returned_df.respond_to?(:callback) && returned_df.respond_to?(:errback)
136
+ returned_df.callback do
137
+ #{send_name}(*args)
138
+ ::EM.watch(self.socket, Watcher, self, df).notify_readable = true
139
+ end
140
+ returned_df.errback do |ex|
141
+ df.fail(ex)
142
+ end
143
+ return df
144
+ end
145
+ ensure
146
+ self.async_autoreconnect = true
147
+ end
148
+ end
149
+ #{send_name}(*args)
94
150
  else
95
151
  raise e
96
152
  end
97
153
  end
98
- df = ::EM::DefaultDeferrable.new
99
154
  ::EM.watch(self.socket, Watcher, self, df).notify_readable = true
100
- if block_given?
101
- df.callback(&blk)
102
- df.errback(&blk)
103
- end
104
155
  df
105
156
  end
106
157
  EOD
@@ -1,4 +1,5 @@
1
1
  $:.unshift "lib"
2
+ gem 'eventmachine', '>= 1.0.0.beta.1'
2
3
  require 'date'
3
4
  require 'eventmachine'
4
5
  require 'pg/em'
@@ -6,8 +7,10 @@ require 'pg/em'
6
7
  describe PG::EM::Client do
7
8
 
8
9
  it "should create simple table `foo`" do
9
- @client.query('DROP TABLE IF EXISTS foo') do
10
- @client.query('CREATE TABLE foo (id integer,cdate timestamp with time zone,data varchar)') do
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
11
14
  EM.stop
12
15
  end
13
16
  end
@@ -16,6 +19,7 @@ describe PG::EM::Client do
16
19
  it "should populate foo with some data " do
17
20
  EM::Iterator.new(@values).map(proc{ |(data, id), iter|
18
21
  @client.query('INSERT INTO foo (id,cdate,data) VALUES($1,$2,$3) returning cdate', [id, DateTime.now, data]) do |result|
22
+ raise result if result.is_a? ::Exception
19
23
  iter.return(DateTime.parse(result[0]['cdate']))
20
24
  end
21
25
  }, proc{ |results|
@@ -27,8 +31,10 @@ describe PG::EM::Client do
27
31
  end
28
32
 
29
33
  it "should read foo table with prepared statement" do
30
- @client.prepare('get_foo', 'SELECT * FROM foo order by id') do
34
+ @client.prepare('get_foo', 'SELECT * FROM foo order by id') do |result|
35
+ raise result if result.is_a? ::Exception
31
36
  @client.exec_prepared('get_foo') do |result|
37
+ raise result if result.is_a? ::Exception
32
38
  result.each_with_index do |row, i|
33
39
  row['id'].to_i.should == i
34
40
  DateTime.parse(row['cdate']).should == @cdates[i]
@@ -0,0 +1,69 @@
1
+ $:.unshift "lib"
2
+ gem 'eventmachine', '= 0.12.10'
3
+ require 'date'
4
+ require 'eventmachine'
5
+ require 'pg/em'
6
+
7
+ describe PG::EM::Client do
8
+
9
+ it "should create simple table `foo`" do
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
18
+
19
+ it "should populate foo with some data " do
20
+ values = @values.dup
21
+ results = []
22
+ do_query = proc do
23
+ data, id = values.shift
24
+ @client.query('INSERT INTO foo (id,cdate,data) VALUES($1,$2,$3) returning cdate', [id, DateTime.now, data]) do |result|
25
+ raise result if result.is_a? ::Exception
26
+ results << DateTime.parse(result[0]['cdate'])
27
+ if values.empty?
28
+ @cdates.replace results
29
+ results.length.should == @values.length
30
+ results.each {|r| r.class.should == DateTime }
31
+ EM.stop
32
+ else
33
+ do_query.call
34
+ end
35
+ end
36
+ end
37
+ do_query.call
38
+ end
39
+
40
+ it "should read foo table with prepared statement" do
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
64
+
65
+ after(:all) do
66
+ @client.query 'ROLLBACK TRANSACTION'
67
+ @client.close
68
+ end
69
+ end
metadata CHANGED
@@ -1,126 +1,124 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: em-pg-client
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.0
3
+ version: !ruby/object:Gem::Version
5
4
  prerelease:
5
+ version: 0.1.1
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Rafal Michalski
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-29 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
12
+
13
+ date: 2012-04-27 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
15
16
  name: pg
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: 0.13.2
22
- type: :runtime
23
17
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
18
+ requirement: &id001 !ruby/object:Gem::Requirement
25
19
  none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
29
23
  version: 0.13.2
30
- - !ruby/object:Gem::Dependency
31
- name: eventmachine
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: 0.12.10
38
24
  type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: eventmachine
39
28
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
29
+ requirement: &id002 !ruby/object:Gem::Requirement
41
30
  none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
45
34
  version: 0.12.10
46
- - !ruby/object:Gem::Dependency
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
47
38
  name: rspec
48
- requirement: !ruby/object:Gem::Requirement
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
49
41
  none: false
50
- requirements:
42
+ requirements:
51
43
  - - ~>
52
- - !ruby/object:Gem::Version
44
+ - !ruby/object:Gem::Version
53
45
  version: 2.8.0
54
46
  type: :development
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: eventmachine
55
50
  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
62
- - !ruby/object:Gem::Dependency
63
- name: em-synchrony
64
- requirement: !ruby/object:Gem::Requirement
51
+ requirement: &id004 !ruby/object:Gem::Requirement
65
52
  none: false
66
- requirements:
67
- - - ~>
68
- - !ruby/object:Gem::Version
69
- version: 1.0.0
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 1.0.0.beta.1
70
57
  type: :development
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: em-synchrony
71
61
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
62
+ requirement: &id005 !ruby/object:Gem::Requirement
73
63
  none: false
74
- requirements:
64
+ requirements:
75
65
  - - ~>
76
- - !ruby/object:Gem::Version
66
+ - !ruby/object:Gem::Version
77
67
  version: 1.0.0
68
+ type: :development
69
+ version_requirements: *id005
78
70
  description: PostgreSQL asynchronous EventMachine client (ruby-pg) wrapper
79
71
  email: rafal@yeondir.com
80
72
  executables: []
73
+
81
74
  extensions: []
82
- extra_rdoc_files:
75
+
76
+ extra_rdoc_files:
83
77
  - README.rdoc
84
78
  - BENCHMARKS.rdoc
85
- files:
79
+ files:
86
80
  - BENCHMARKS.rdoc
81
+ - HISTORY.rdoc
87
82
  - README.rdoc
88
83
  - Rakefile
89
84
  - benchmarks/em_pg.rb
90
85
  - em-pg-client.gemspec
91
86
  - lib/em-synchrony/pg.rb
92
87
  - lib/pg/em.rb
93
- - spec/em_client.rb
88
+ - spec/em_devel_client.rb
89
+ - spec/em_release_client.rb
94
90
  - spec/em_synchrony_client.rb
95
91
  homepage: http://github.com/royaltm/ruby-em-pg-client
96
92
  licenses: []
93
+
97
94
  post_install_message:
98
- rdoc_options:
95
+ rdoc_options:
99
96
  - --title
100
97
  - em-pg-client
101
98
  - --main
102
99
  - README.rdoc
103
- require_paths:
100
+ require_paths:
104
101
  - lib
105
- required_ruby_version: !ruby/object:Gem::Requirement
102
+ required_ruby_version: !ruby/object:Gem::Requirement
106
103
  none: false
107
- requirements:
108
- - - ! '>='
109
- - !ruby/object:Gem::Version
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
110
107
  version: 1.9.1
111
- required_rubygems_version: !ruby/object:Gem::Requirement
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
109
  none: false
113
- requirements:
114
- - - ! '>='
115
- - !ruby/object:Gem::Version
116
- version: '0'
117
- requirements:
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: "0"
114
+ requirements:
118
115
  - PostgreSQL server
119
116
  rubyforge_project:
120
- rubygems_version: 1.8.21
117
+ rubygems_version: 1.8.17
121
118
  signing_key:
122
119
  specification_version: 3
123
120
  summary: EventMachine PostgreSQL client
124
- test_files:
125
- - spec/em_client.rb
121
+ test_files:
126
122
  - spec/em_synchrony_client.rb
123
+ - spec/em_devel_client.rb
124
+ - spec/em_release_client.rb