em-pg-client 0.2.1 → 0.3.0
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/.yardopts +1 -0
- data/{BENCHMARKS.rdoc → BENCHMARKS.md} +15 -10
- data/{HISTORY.rdoc → HISTORY.md} +32 -5
- data/LICENSE +21 -0
- data/README.md +392 -0
- data/Rakefile +30 -14
- data/em-pg-client.gemspec +8 -7
- data/lib/em-pg-client.rb +1 -0
- data/lib/em-synchrony/pg.rb +2 -107
- data/lib/pg/em-version.rb +5 -0
- data/lib/pg/em.rb +638 -344
- data/lib/pg/em/client/connect_watcher.rb +65 -0
- data/lib/pg/em/client/watcher.rb +102 -0
- data/lib/pg/em/connection_pool.rb +448 -0
- data/lib/pg/em/featured_deferrable.rb +43 -0
- data/spec/connection_pool_helpers.rb +89 -0
- data/spec/{em_devel_client.rb → em_client.rb} +3 -2
- data/spec/em_client_autoreconnect.rb +268 -144
- data/spec/em_client_common.rb +55 -54
- data/spec/em_synchrony_client.rb +254 -5
- data/spec/em_synchrony_client_autoreconnect.rb +154 -130
- data/spec/pg_em_client_connect_finish.rb +54 -0
- data/spec/pg_em_client_connect_timeout.rb +91 -0
- data/spec/pg_em_client_options.rb +85 -0
- data/spec/pg_em_connection_pool.rb +655 -0
- data/spec/pg_em_featured_deferrable.rb +125 -0
- metadata +64 -34
- data/README.rdoc +0 -431
- data/spec/em_release_client.rb +0 -39
@@ -0,0 +1,43 @@
|
|
1
|
+
module PG
|
2
|
+
module EM
|
3
|
+
|
4
|
+
# Deferrable with error protectors
|
5
|
+
#
|
6
|
+
# Author:: Rafal Michalski
|
7
|
+
class FeaturedDeferrable < ::EM::DefaultDeferrable
|
8
|
+
|
9
|
+
def initialize(&blk)
|
10
|
+
completion(&blk) if block_given?
|
11
|
+
end
|
12
|
+
|
13
|
+
def completion(&blk)
|
14
|
+
callback(&blk)
|
15
|
+
errback(&blk)
|
16
|
+
end
|
17
|
+
|
18
|
+
def protect(fail_value = nil)
|
19
|
+
yield
|
20
|
+
rescue Exception => e
|
21
|
+
::EM.next_tick { fail e }
|
22
|
+
fail_value
|
23
|
+
end
|
24
|
+
|
25
|
+
def protect_and_succeed(fail_value = nil)
|
26
|
+
ret = yield
|
27
|
+
rescue Exception => e
|
28
|
+
::EM.next_tick { fail e }
|
29
|
+
fail_value
|
30
|
+
else
|
31
|
+
::EM.next_tick { succeed ret }
|
32
|
+
ret
|
33
|
+
end
|
34
|
+
|
35
|
+
# bind deferred status of this deferrable to other +df+
|
36
|
+
def bind_status(df)
|
37
|
+
df.callback { |*a| succeed(*a) }
|
38
|
+
df.errback { |*a| fail(*a) }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module ConnectionPoolHelpers
|
2
|
+
def sleep_one_tick
|
3
|
+
f = Fiber.current
|
4
|
+
EM.next_tick { f.resume }
|
5
|
+
Fiber.yield
|
6
|
+
end
|
7
|
+
|
8
|
+
def create_connection
|
9
|
+
client.allocate.tap do |conn|
|
10
|
+
conn.stub(:query) do |query|
|
11
|
+
query.should start_with 'f'
|
12
|
+
checkpoint.check_defer
|
13
|
+
f = Fiber.current
|
14
|
+
conn.instance_eval { @fiber = f }
|
15
|
+
EM.next_tick {
|
16
|
+
conn.instance_variable_get(:@fiber).should be f
|
17
|
+
f.resume
|
18
|
+
}
|
19
|
+
Fiber.yield
|
20
|
+
if query == 'fee'
|
21
|
+
conn.should_receive(:status).once.and_return(PG::CONNECTION_BAD)
|
22
|
+
conn.should_receive(:finished?).once.and_return(false)
|
23
|
+
conn.should_receive(:finish).once
|
24
|
+
raise PG::ConnectionBad
|
25
|
+
else
|
26
|
+
:result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
conn.stub(:query_defer) do |query|
|
30
|
+
query.should start_with 'b'
|
31
|
+
checkpoint.check_fiber
|
32
|
+
deferrable.new.tap do |df|
|
33
|
+
conn.instance_eval { @defer = df }
|
34
|
+
EM.next_tick {
|
35
|
+
conn.instance_variable_get(:@defer).should be df
|
36
|
+
if query == 'bzz'
|
37
|
+
conn.should_receive(:status).once.and_return(PG::CONNECTION_BAD)
|
38
|
+
conn.should_receive(:finished?).once.and_return(false)
|
39
|
+
conn.should_receive(:finish).once
|
40
|
+
df.fail pgerror
|
41
|
+
else
|
42
|
+
df.succeed :result
|
43
|
+
end
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_queries(pool, queries)
|
51
|
+
EM.synchrony do
|
52
|
+
EM.add_timer(2) { raise 'timeout' }
|
53
|
+
progress = Set.new
|
54
|
+
queries.each_with_index do |query, i|
|
55
|
+
case query
|
56
|
+
when 'foo'
|
57
|
+
Fiber.new do
|
58
|
+
pool.query(query).should be :result
|
59
|
+
progress.delete i
|
60
|
+
end.resume
|
61
|
+
when 'bar'
|
62
|
+
pool.query_defer(query).callback do |result|
|
63
|
+
result.should be :result
|
64
|
+
progress.delete i
|
65
|
+
end.should_not_receive(:fail)
|
66
|
+
when 'fee'
|
67
|
+
Fiber.new do
|
68
|
+
expect do
|
69
|
+
pool.query(query)
|
70
|
+
end.to raise_error(PG::ConnectionBad)
|
71
|
+
progress.delete i
|
72
|
+
end.resume
|
73
|
+
when 'bzz'
|
74
|
+
pool.query_defer(query).errback do |err|
|
75
|
+
err.should be pgerror
|
76
|
+
progress.delete i
|
77
|
+
end.should_not_receive(:succeed)
|
78
|
+
end
|
79
|
+
progress << i
|
80
|
+
end
|
81
|
+
progress.should eq Set.new(0...queries.length)
|
82
|
+
begin
|
83
|
+
yield progress
|
84
|
+
sleep_one_tick
|
85
|
+
end until progress.empty?
|
86
|
+
EM.stop
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
$:.unshift "lib"
|
2
|
-
gem 'eventmachine', '
|
2
|
+
gem 'eventmachine', '~> 1.0.0'
|
3
3
|
gem 'pg', ENV['EM_PG_CLIENT_TEST_PG_VERSION']
|
4
4
|
require 'date'
|
5
5
|
require 'eventmachine'
|
@@ -15,7 +15,8 @@ describe PG::EM::Client do
|
|
15
15
|
|
16
16
|
it "should populate foo with some data " do
|
17
17
|
EM::Iterator.new(@values).map(proc{ |(data, id), iter|
|
18
|
-
@client.
|
18
|
+
@client.query_defer('INSERT INTO foo (id,cdate,data) VALUES($1,$2,$3) returning cdate',
|
19
|
+
[id, DateTime.now, data]) do |result|
|
19
20
|
result.should be_an_instance_of PG::Result
|
20
21
|
iter.return(DateTime.parse(result[0]['cdate']))
|
21
22
|
end.should be_a_kind_of ::EM::DefaultDeferrable
|
@@ -1,144 +1,268 @@
|
|
1
|
-
$:.unshift "lib"
|
2
|
-
|
3
|
-
|
4
|
-
require '
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
begin
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
@
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
end
|
144
|
-
|
1
|
+
$:.unshift "lib"
|
2
|
+
gem 'eventmachine', '~> 1.0.0'
|
3
|
+
gem 'pg', ENV['EM_PG_CLIENT_TEST_PG_VERSION']
|
4
|
+
require 'date'
|
5
|
+
require 'eventmachine'
|
6
|
+
require 'pg/em'
|
7
|
+
|
8
|
+
$pgserver_cmd_stop = %Q[sudo -i -u postgres pg_ctl -D "#{ENV['PGDATA']}" stop -s -m fast]
|
9
|
+
$pgserver_cmd_start = %Q[sudo -i -u postgres pg_ctl -D "#{ENV['PGDATA']}" start -s -w]
|
10
|
+
|
11
|
+
shared_context 'pg-em common' do
|
12
|
+
around(:each) do |testcase|
|
13
|
+
EM.run(&testcase)
|
14
|
+
end
|
15
|
+
|
16
|
+
after(:all) do
|
17
|
+
@client.close
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'pg-em async connect fail' do
|
22
|
+
around(:each) do |testcase|
|
23
|
+
begin
|
24
|
+
system($pgserver_cmd_stop).should be_true
|
25
|
+
testcase.call
|
26
|
+
ensure
|
27
|
+
system($pgserver_cmd_start).should be_true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should not connect when server is down" do
|
32
|
+
error = nil
|
33
|
+
EM.run do
|
34
|
+
EM.add_timer(1) { EM.stop }
|
35
|
+
df = PG::EM::Client.async_connect
|
36
|
+
df.callback {|c| c.close }
|
37
|
+
df.errback do |err|
|
38
|
+
error = err
|
39
|
+
EM.stop
|
40
|
+
end
|
41
|
+
end
|
42
|
+
error.should be_an_instance_of PG::ConnectionBad
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'pg-em default autoreconnect' do
|
47
|
+
include_context 'pg-em common'
|
48
|
+
|
49
|
+
it "should not have modified argument Hash" do
|
50
|
+
begin
|
51
|
+
@options.should eq(async_autoreconnect: true)
|
52
|
+
ensure
|
53
|
+
EM.stop
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should get database size using query" do
|
58
|
+
@tested_proc.call
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should get database size using query after server restart" do
|
62
|
+
system($pgserver_cmd_stop).should be_true
|
63
|
+
system($pgserver_cmd_start).should be_true
|
64
|
+
@tested_proc.call
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should not get database size using query after server shutdown" do
|
68
|
+
system($pgserver_cmd_stop).should be_true
|
69
|
+
@client.query_defer('SELECT pg_database_size(current_database());') do |ex|
|
70
|
+
ex.should be_an_instance_of @client.host.include?('/') ? PG::UnableToSend : PG::ConnectionBad
|
71
|
+
EM.stop
|
72
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should get database size using query after server startup" do
|
76
|
+
system($pgserver_cmd_start).should be_true
|
77
|
+
@tested_proc.call
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should fail on invalid query after server restart" do
|
81
|
+
system($pgserver_cmd_stop).should be_true
|
82
|
+
system($pgserver_cmd_start).should be_true
|
83
|
+
@client.query_defer('SELLECT 1') do |ex|
|
84
|
+
ex.should be_an_instance_of PG::SyntaxError
|
85
|
+
EM.stop
|
86
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should fail when in transaction after server restart" do
|
90
|
+
@client.query_defer('BEGIN') do |result|
|
91
|
+
result.should be_an_instance_of PG::Result
|
92
|
+
system($pgserver_cmd_stop).should be_true
|
93
|
+
system($pgserver_cmd_start).should be_true
|
94
|
+
@client.query_defer('SELECT pg_database_size(current_database());') do |ex|
|
95
|
+
ex.should be_an_instance_of @client.host.include?('/') ? PG::UnableToSend : PG::ConnectionBad
|
96
|
+
@tested_proc.call
|
97
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
before(:all) do
|
102
|
+
@tested_proc = proc do
|
103
|
+
@client.query_defer('SELECT pg_database_size(current_database());') do |result|
|
104
|
+
result.should be_an_instance_of PG::Result
|
105
|
+
result[0]['pg_database_size'].to_i.should be > 0
|
106
|
+
EM.stop
|
107
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
108
|
+
end
|
109
|
+
@options = {async_autoreconnect: true}
|
110
|
+
@client = PG::EM::Client.new(@options)
|
111
|
+
@client.set_notice_processor {|msg| puts "warning from pgsql: #{msg.to_s.chomp.inspect}"}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe 'pg-em autoreconnect with on_autoreconnect' do
|
116
|
+
include_context 'pg-em common'
|
117
|
+
|
118
|
+
it "should not have modified argument Hash" do
|
119
|
+
begin
|
120
|
+
@options.should eq(on_autoreconnect: @on_autoreconnect)
|
121
|
+
ensure
|
122
|
+
EM.stop
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should get database size using prepared statement"do
|
127
|
+
@tested_proc.call
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should get database size using prepared statement after server restart" do
|
131
|
+
system($pgserver_cmd_stop).should be_true
|
132
|
+
system($pgserver_cmd_start).should be_true
|
133
|
+
@tested_proc.call
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should fail on invalid query after server restart" do
|
137
|
+
system($pgserver_cmd_stop).should be_true
|
138
|
+
system($pgserver_cmd_start).should be_true
|
139
|
+
@client.query_defer('SELLECT 1') do |ex|
|
140
|
+
ex.should be_an_instance_of PG::SyntaxError
|
141
|
+
EM.stop
|
142
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should fail when in transaction after server restart" do
|
146
|
+
@client.query_defer('BEGIN') do |result|
|
147
|
+
result.should be_an_instance_of PG::Result
|
148
|
+
system($pgserver_cmd_stop).should be_true
|
149
|
+
system($pgserver_cmd_start).should be_true
|
150
|
+
@client.query_defer('SELECT pg_database_size(current_database());') do |ex|
|
151
|
+
ex.should be_an_instance_of @client.host.include?('/') ? PG::UnableToSend : PG::ConnectionBad
|
152
|
+
@tested_proc.call
|
153
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should fail on false from on_autoreconnect after server restart" do
|
158
|
+
@client.on_autoreconnect = proc { false }
|
159
|
+
system($pgserver_cmd_stop).should be_true
|
160
|
+
system($pgserver_cmd_start).should be_true
|
161
|
+
@client.query_defer('SELECT pg_database_size(current_database());') do |ex|
|
162
|
+
ex.should be_an_instance_of @client.host.include?('/') ? PG::UnableToSend : PG::ConnectionBad
|
163
|
+
EM.stop
|
164
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should complete on true from on_autoreconnect after server restart" do
|
168
|
+
@client.on_autoreconnect = proc { true }
|
169
|
+
system($pgserver_cmd_stop).should be_true
|
170
|
+
system($pgserver_cmd_start).should be_true
|
171
|
+
@client.query_defer('SELECT pg_database_size(current_database());') do |result|
|
172
|
+
result.should be_an_instance_of PG::Result
|
173
|
+
result[0]['pg_database_size'].to_i.should be > 0
|
174
|
+
EM.stop
|
175
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should fail on query with true from on_autoreconnect after restart" do
|
179
|
+
@client.on_autoreconnect = proc { true }
|
180
|
+
system($pgserver_cmd_stop).should be_true
|
181
|
+
system($pgserver_cmd_start).should be_true
|
182
|
+
@client.query_defer('SELLECT 1') do |ex|
|
183
|
+
ex.should be_an_instance_of PG::SyntaxError
|
184
|
+
EM.stop
|
185
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should fail on on_autoreconnect deferrable fail after server restart" do
|
189
|
+
@client.on_autoreconnect = proc do
|
190
|
+
::EM::DefaultDeferrable.new.tap {|df| df.fail :boo }
|
191
|
+
end
|
192
|
+
system($pgserver_cmd_stop).should be_true
|
193
|
+
system($pgserver_cmd_start).should be_true
|
194
|
+
@client.query_defer('SELECT 1') do |ex|
|
195
|
+
ex.should be :boo
|
196
|
+
EM.stop
|
197
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should fail on raised error in on_autoreconnect after server restart" do
|
201
|
+
@client.on_autoreconnect = proc do
|
202
|
+
raise TypeError
|
203
|
+
end
|
204
|
+
system($pgserver_cmd_stop).should be_true
|
205
|
+
system($pgserver_cmd_start).should be_true
|
206
|
+
@client.query_defer('SELECT 1') do |ex|
|
207
|
+
ex.should be_an_instance_of TypeError
|
208
|
+
EM.stop
|
209
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
210
|
+
end
|
211
|
+
|
212
|
+
before(:all) do
|
213
|
+
@tested_proc = proc do
|
214
|
+
@client.exec_prepared_defer('get_db_size') do |result|
|
215
|
+
result.should be_an_instance_of PG::Result
|
216
|
+
result[0]['pg_database_size'].to_i.should be > 0
|
217
|
+
EM.stop
|
218
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
219
|
+
end
|
220
|
+
@on_autoreconnect = proc do |client, ex|
|
221
|
+
df = client.prepare_defer('get_db_size', 'SELECT pg_database_size(current_database());')
|
222
|
+
df.should be_a_kind_of ::EM::DefaultDeferrable
|
223
|
+
df
|
224
|
+
end
|
225
|
+
@options = {on_autoreconnect: @on_autoreconnect}
|
226
|
+
@client = PG::EM::Client.new(@options)
|
227
|
+
@client.set_notice_processor {|msg| puts "warning from pgsql: #{msg.to_s.chomp.inspect}"}
|
228
|
+
@client.prepare('get_db_size', 'SELECT pg_database_size(current_database());')
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe 'pg-em with autoreconnect disabled' do
|
233
|
+
include_context 'pg-em common'
|
234
|
+
|
235
|
+
it "should get database size using query" do
|
236
|
+
@tested_proc.call
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should not get database size using query after server restart" do
|
240
|
+
system($pgserver_cmd_stop).should be_true
|
241
|
+
system($pgserver_cmd_start).should be_true
|
242
|
+
@client.query_defer('SELECT pg_database_size(current_database());') do |ex|
|
243
|
+
ex.should be_an_instance_of @client.host.include?('/') ? PG::UnableToSend : PG::ConnectionBad
|
244
|
+
EM.stop
|
245
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should get database size using query after async manual connection reset" do
|
249
|
+
@client.status.should be PG::CONNECTION_BAD
|
250
|
+
@client.async_reset do |conn|
|
251
|
+
conn.should be @client
|
252
|
+
@client.status.should be PG::CONNECTION_OK
|
253
|
+
@tested_proc.call
|
254
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
255
|
+
end
|
256
|
+
|
257
|
+
before(:all) do
|
258
|
+
@tested_proc = proc do
|
259
|
+
@client.query_defer('SELECT pg_database_size(current_database());') do |result|
|
260
|
+
result.should be_an_instance_of PG::Result
|
261
|
+
result[0]['pg_database_size'].to_i.should be > 0
|
262
|
+
EM.stop
|
263
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
264
|
+
end
|
265
|
+
@client = PG::EM::Client.new
|
266
|
+
@client.set_notice_processor {|msg| puts "warning from pgsql: #{msg.to_s.chomp.inspect}"}
|
267
|
+
end
|
268
|
+
end
|