em-pg-client 0.3.0 → 0.3.1
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/.rspec +1 -0
- data/.travis.yml +31 -0
- data/Gemfile +5 -0
- data/HISTORY.md +10 -0
- data/README.md +31 -10
- data/Rakefile +62 -25
- data/benchmarks/em_pg.rb +15 -12
- data/em-pg-client.gemspec +3 -1
- data/examples/single_row_mode.rb +67 -0
- data/lib/pg/em-version.rb +1 -1
- data/lib/pg/em.rb +187 -54
- data/lib/pg/em/client/connect_watcher.rb +2 -8
- data/lib/pg/em/client/watcher.rb +45 -21
- data/spec/em_client_autoreconnect.rb +140 -8
- data/spec/em_client_common.rb +77 -0
- data/spec/em_synchrony_client.rb +77 -9
- data/spec/em_synchrony_client_autoreconnect.rb +120 -6
- data/spec/pg_em_client_connect_finish.rb +1 -1
- data/spec/pg_em_client_options.rb +13 -3
- data/spec/spec_helper.rb +9 -0
- metadata +42 -4
@@ -17,9 +17,7 @@ module PG
|
|
17
17
|
@timer = ::EM::Timer.new(timeout) do
|
18
18
|
detach
|
19
19
|
@deferrable.protect do
|
20
|
-
|
21
|
-
error.instance_variable_set(:@connection, @client)
|
22
|
-
raise error
|
20
|
+
@client.raise_error ConnectionBad, "timeout expired (async)"
|
23
21
|
end
|
24
22
|
end
|
25
23
|
end
|
@@ -45,11 +43,7 @@ module PG
|
|
45
43
|
@timer.cancel if @timer
|
46
44
|
detach
|
47
45
|
@deferrable.protect_and_succeed do
|
48
|
-
unless polling_ok
|
49
|
-
error = ConnectionBad.new(@client.error_message)
|
50
|
-
error.instance_variable_set(:@connection, @client)
|
51
|
-
raise error
|
52
|
-
end
|
46
|
+
@client.raise_error ConnectionBad unless polling_ok
|
53
47
|
@client.set_default_encoding unless reconnecting?
|
54
48
|
@client
|
55
49
|
end
|
data/lib/pg/em/client/watcher.rb
CHANGED
@@ -17,17 +17,31 @@ module PG
|
|
17
17
|
@is_connected
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
|
20
|
+
def one_result_mode?
|
21
|
+
@one_result_mode
|
22
|
+
end
|
23
|
+
|
24
|
+
def watch_results(deferrable, send_proc=nil, one_result_mode=false)
|
25
|
+
@one_result_mode = one_result_mode
|
22
26
|
@last_result = nil
|
23
27
|
@deferrable = deferrable
|
24
28
|
@send_proc = send_proc
|
25
|
-
|
26
|
-
if
|
27
|
-
@
|
28
|
-
|
29
|
+
cancel_timer
|
30
|
+
if @client.is_busy
|
31
|
+
if @client.status == PG::CONNECTION_OK
|
32
|
+
self.notify_readable = true
|
33
|
+
if (timeout = @client.query_timeout) > 0
|
34
|
+
@notify_timestamp = Time.now
|
35
|
+
setup_timer timeout
|
36
|
+
end
|
37
|
+
else
|
38
|
+
@deferrable.protect do
|
39
|
+
@client.raise_error ConnectionBad
|
40
|
+
end
|
41
|
+
end
|
29
42
|
else
|
30
|
-
|
43
|
+
self.notify_readable = true
|
44
|
+
fetch_results
|
31
45
|
end
|
32
46
|
self
|
33
47
|
end
|
@@ -39,9 +53,7 @@ module PG
|
|
39
53
|
self.notify_readable = false
|
40
54
|
@client.async_command_aborted = true
|
41
55
|
@deferrable.protect do
|
42
|
-
|
43
|
-
error.instance_variable_set(:@connection, @client)
|
44
|
-
raise error
|
56
|
+
@client.raise_error ConnectionBad, "query timeout expired (async)"
|
45
57
|
end
|
46
58
|
else
|
47
59
|
setup_timer timeout, last_interval
|
@@ -56,20 +68,20 @@ module PG
|
|
56
68
|
end
|
57
69
|
end
|
58
70
|
|
59
|
-
# Carefully extract
|
71
|
+
# Carefully extract results without
|
60
72
|
# blocking the EventMachine reactor.
|
61
|
-
def
|
73
|
+
def fetch_results
|
62
74
|
result = false
|
63
75
|
@client.consume_input
|
64
76
|
until @client.is_busy
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
77
|
+
single_result = @client.blocking_get_result
|
78
|
+
if one_result_mode?
|
79
|
+
result = single_result
|
80
|
+
break
|
81
|
+
elsif single_result.nil?
|
82
|
+
if result = @last_result
|
83
|
+
result.check
|
70
84
|
end
|
71
|
-
result.check
|
72
|
-
cancel_timer
|
73
85
|
break
|
74
86
|
end
|
75
87
|
@last_result.clear if @last_result
|
@@ -78,22 +90,34 @@ module PG
|
|
78
90
|
rescue Exception => e
|
79
91
|
self.notify_readable = false
|
80
92
|
cancel_timer
|
93
|
+
send_proc = @send_proc
|
94
|
+
@send_proc = nil
|
95
|
+
df = @deferrable
|
96
|
+
# prevent unbind error on auto re-connect
|
97
|
+
@deferrable = false
|
81
98
|
if e.is_a?(PG::Error)
|
82
|
-
@client.async_autoreconnect!(
|
99
|
+
@client.async_autoreconnect!(df, e, &send_proc)
|
83
100
|
else
|
84
|
-
|
101
|
+
df.fail(e)
|
85
102
|
end
|
86
103
|
else
|
87
104
|
if result == false
|
88
105
|
@notify_timestamp = Time.now if @timer
|
89
106
|
else
|
90
107
|
self.notify_readable = false
|
108
|
+
cancel_timer
|
109
|
+
@send_proc = nil
|
91
110
|
@deferrable.succeed(result)
|
92
111
|
end
|
93
112
|
end
|
94
113
|
|
114
|
+
alias_method :notify_readable, :fetch_results
|
115
|
+
|
95
116
|
def unbind
|
96
117
|
@is_connected = false
|
118
|
+
@deferrable.protect do
|
119
|
+
@client.raise_error ConnectionBad, "connection reset"
|
120
|
+
end if @deferrable
|
97
121
|
end
|
98
122
|
end
|
99
123
|
|
@@ -5,8 +5,10 @@ require 'date'
|
|
5
5
|
require 'eventmachine'
|
6
6
|
require 'pg/em'
|
7
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]
|
8
|
+
$pgserver_cmd_stop = ENV['PG_CTL_STOP_CMD'] || %Q[sudo -i -u postgres pg_ctl -D "#{ENV['PGDATA']}" stop -s -m fast]
|
9
|
+
$pgserver_cmd_start = ENV['PG_CTL_START_CMD'] || %Q[sudo -i -u postgres pg_ctl -D "#{ENV['PGDATA']}" start -s -w]
|
10
|
+
|
11
|
+
DISCONNECTED_ERROR = ENV['PGHOST'].include?('/') ? PG::UnableToSend : PG::ConnectionBad
|
10
12
|
|
11
13
|
shared_context 'pg-em common' do
|
12
14
|
around(:each) do |testcase|
|
@@ -67,7 +69,7 @@ describe 'pg-em default autoreconnect' do
|
|
67
69
|
it "should not get database size using query after server shutdown" do
|
68
70
|
system($pgserver_cmd_stop).should be_true
|
69
71
|
@client.query_defer('SELECT pg_database_size(current_database());') do |ex|
|
70
|
-
ex.should be_an_instance_of
|
72
|
+
ex.should be_an_instance_of DISCONNECTED_ERROR
|
71
73
|
EM.stop
|
72
74
|
end.should be_a_kind_of ::EM::DefaultDeferrable
|
73
75
|
end
|
@@ -92,12 +94,47 @@ describe 'pg-em default autoreconnect' do
|
|
92
94
|
system($pgserver_cmd_stop).should be_true
|
93
95
|
system($pgserver_cmd_start).should be_true
|
94
96
|
@client.query_defer('SELECT pg_database_size(current_database());') do |ex|
|
95
|
-
ex.should be_an_instance_of
|
97
|
+
ex.should be_an_instance_of DISCONNECTED_ERROR
|
96
98
|
@tested_proc.call
|
97
99
|
end.should be_a_kind_of ::EM::DefaultDeferrable
|
98
100
|
end
|
99
101
|
end
|
100
102
|
|
103
|
+
it "should fail to get last result asynchronously after server restart" do
|
104
|
+
@client.send_query('SELECT pg_sleep(5); SELECT pg_database_size(current_database());')
|
105
|
+
system($pgserver_cmd_stop).should be_true
|
106
|
+
system($pgserver_cmd_start).should be_true
|
107
|
+
@client.get_last_result_defer do |ex|
|
108
|
+
ex.should be_an_instance_of PG::ConnectionBad
|
109
|
+
@client.status.should be PG::CONNECTION_OK
|
110
|
+
@client.get_last_result_defer do |result|
|
111
|
+
result.should be_nil
|
112
|
+
EM.stop
|
113
|
+
end
|
114
|
+
end.should be_a_kind_of EM::DefaultDeferrable
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should fail to get each result asynchronously after server restart" do
|
118
|
+
@client.send_query('SELECT pg_sleep(5); SELECT pg_database_size(current_database());')
|
119
|
+
system($pgserver_cmd_stop).should be_true
|
120
|
+
system($pgserver_cmd_start).should be_true
|
121
|
+
@client.get_result_defer do |result|
|
122
|
+
result.should be_an_instance_of PG::Result
|
123
|
+
expect do
|
124
|
+
result.check
|
125
|
+
end.to raise_error PG::Error
|
126
|
+
@client.status.should be PG::CONNECTION_OK
|
127
|
+
@client.get_result_defer do |ex|
|
128
|
+
ex.should be_an_instance_of PG::ConnectionBad
|
129
|
+
@client.status.should be PG::CONNECTION_OK
|
130
|
+
@client.get_result_defer do |result|
|
131
|
+
result.should be_nil
|
132
|
+
EM.stop
|
133
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
134
|
+
end.should be_a_kind_of EM::DefaultDeferrable
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
101
138
|
before(:all) do
|
102
139
|
@tested_proc = proc do
|
103
140
|
@client.query_defer('SELECT pg_database_size(current_database());') do |result|
|
@@ -148,7 +185,7 @@ describe 'pg-em autoreconnect with on_autoreconnect' do
|
|
148
185
|
system($pgserver_cmd_stop).should be_true
|
149
186
|
system($pgserver_cmd_start).should be_true
|
150
187
|
@client.query_defer('SELECT pg_database_size(current_database());') do |ex|
|
151
|
-
ex.should be_an_instance_of
|
188
|
+
ex.should be_an_instance_of DISCONNECTED_ERROR
|
152
189
|
@tested_proc.call
|
153
190
|
end.should be_a_kind_of ::EM::DefaultDeferrable
|
154
191
|
end
|
@@ -159,7 +196,7 @@ describe 'pg-em autoreconnect with on_autoreconnect' do
|
|
159
196
|
system($pgserver_cmd_stop).should be_true
|
160
197
|
system($pgserver_cmd_start).should be_true
|
161
198
|
@client.query_defer('SELECT pg_database_size(current_database());') do |ex|
|
162
|
-
ex.should be_an_instance_of
|
199
|
+
ex.should be_an_instance_of DISCONNECTED_ERROR
|
163
200
|
EM.stop
|
164
201
|
end.should be_a_kind_of ::EM::DefaultDeferrable
|
165
202
|
end
|
@@ -209,6 +246,45 @@ describe 'pg-em autoreconnect with on_autoreconnect' do
|
|
209
246
|
end.should be_a_kind_of ::EM::DefaultDeferrable
|
210
247
|
end
|
211
248
|
|
249
|
+
it "should fail to get last result asynchronously after server restart" do
|
250
|
+
@client.on_autoreconnect = proc { true }
|
251
|
+
@client.send_query('SELECT pg_sleep(5); SELECT pg_database_size(current_database());')
|
252
|
+
system($pgserver_cmd_stop).should be_true
|
253
|
+
system($pgserver_cmd_start).should be_true
|
254
|
+
@client.get_last_result_defer do |ex|
|
255
|
+
ex.should be_an_instance_of PG::ConnectionBad
|
256
|
+
@client.status.should be PG::CONNECTION_OK
|
257
|
+
@client.get_last_result_defer do |result|
|
258
|
+
result.should be_nil
|
259
|
+
EM.stop
|
260
|
+
end
|
261
|
+
end.should be_a_kind_of EM::DefaultDeferrable
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should fail to get each result asynchronously after server restart" do
|
265
|
+
@client.on_autoreconnect = proc {
|
266
|
+
EM::DefaultDeferrable.new.tap {|df| df.succeed }
|
267
|
+
}
|
268
|
+
@client.send_query('SELECT pg_sleep(5); SELECT pg_database_size(current_database());')
|
269
|
+
system($pgserver_cmd_stop).should be_true
|
270
|
+
system($pgserver_cmd_start).should be_true
|
271
|
+
@client.get_result_defer do |result|
|
272
|
+
result.should be_an_instance_of PG::Result
|
273
|
+
expect do
|
274
|
+
result.check
|
275
|
+
end.to raise_error PG::Error
|
276
|
+
@client.status.should be PG::CONNECTION_OK
|
277
|
+
@client.get_result_defer do |ex|
|
278
|
+
ex.should be_an_instance_of PG::ConnectionBad
|
279
|
+
@client.status.should be PG::CONNECTION_OK
|
280
|
+
@client.get_result_defer do |result|
|
281
|
+
result.should be_nil
|
282
|
+
EM.stop
|
283
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
284
|
+
end.should be_a_kind_of EM::DefaultDeferrable
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
212
288
|
before(:all) do
|
213
289
|
@tested_proc = proc do
|
214
290
|
@client.exec_prepared_defer('get_db_size') do |result|
|
@@ -240,20 +316,76 @@ describe 'pg-em with autoreconnect disabled' do
|
|
240
316
|
system($pgserver_cmd_stop).should be_true
|
241
317
|
system($pgserver_cmd_start).should be_true
|
242
318
|
@client.query_defer('SELECT pg_database_size(current_database());') do |ex|
|
243
|
-
ex.should be_an_instance_of
|
319
|
+
ex.should be_an_instance_of DISCONNECTED_ERROR
|
320
|
+
@client.status.should be PG::CONNECTION_BAD
|
244
321
|
EM.stop
|
245
322
|
end.should be_a_kind_of ::EM::DefaultDeferrable
|
246
323
|
end
|
247
324
|
|
248
325
|
it "should get database size using query after async manual connection reset" do
|
249
326
|
@client.status.should be PG::CONNECTION_BAD
|
250
|
-
@client.
|
327
|
+
@client.reset_defer do |conn|
|
251
328
|
conn.should be @client
|
252
329
|
@client.status.should be PG::CONNECTION_OK
|
253
330
|
@tested_proc.call
|
254
331
|
end.should be_a_kind_of ::EM::DefaultDeferrable
|
255
332
|
end
|
256
333
|
|
334
|
+
it "should fail to get last result asynchronously after server restart" do
|
335
|
+
system($pgserver_cmd_stop).should be_true
|
336
|
+
system($pgserver_cmd_start).should be_true
|
337
|
+
begin
|
338
|
+
@client.send_query('SELECT pg_sleep(5); SELECT pg_database_size(current_database());')
|
339
|
+
rescue PG::UnableToSend
|
340
|
+
end
|
341
|
+
@client.get_last_result_defer do |ex|
|
342
|
+
ex.should be_an_instance_of PG::ConnectionBad
|
343
|
+
@client.status.should be PG::CONNECTION_BAD
|
344
|
+
@client.get_last_result_defer do |ex|
|
345
|
+
ex.should be_an_instance_of PG::ConnectionBad
|
346
|
+
@client.reset_defer do |conn|
|
347
|
+
conn.should be @client
|
348
|
+
@client.status.should be PG::CONNECTION_OK
|
349
|
+
EM.stop
|
350
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
351
|
+
end
|
352
|
+
end.should be_a_kind_of EM::DefaultDeferrable
|
353
|
+
end
|
354
|
+
|
355
|
+
it "should fail to get each result asynchronously after server restart" do
|
356
|
+
check_get_result = proc do
|
357
|
+
@client.get_result_defer do |ex|
|
358
|
+
ex.should be_an_instance_of PG::ConnectionBad
|
359
|
+
@client.status.should be PG::CONNECTION_BAD
|
360
|
+
@client.reset_defer do |conn|
|
361
|
+
conn.should be @client
|
362
|
+
@client.status.should be PG::CONNECTION_OK
|
363
|
+
EM.stop
|
364
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
365
|
+
end.should be_a_kind_of EM::DefaultDeferrable
|
366
|
+
end
|
367
|
+
system($pgserver_cmd_stop).should be_true
|
368
|
+
system($pgserver_cmd_start).should be_true
|
369
|
+
begin
|
370
|
+
@client.send_query('SELECT pg_sleep(5); SELECT pg_database_size(current_database());')
|
371
|
+
rescue PG::UnableToSend
|
372
|
+
@client.get_result_defer do |result|
|
373
|
+
result.should be_an_instance_of PG::ConnectionBad
|
374
|
+
@client.status.should be PG::CONNECTION_BAD
|
375
|
+
check_get_result.call
|
376
|
+
end
|
377
|
+
else
|
378
|
+
@client.get_result_defer do |result|
|
379
|
+
result.should be_an_instance_of PG::Result
|
380
|
+
expect do
|
381
|
+
result.check
|
382
|
+
end.to raise_error PG::Error
|
383
|
+
@client.status.should be PG::CONNECTION_OK
|
384
|
+
check_get_result.call
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
257
389
|
before(:all) do
|
258
390
|
@tested_proc = proc do
|
259
391
|
@client.query_defer('SELECT pg_database_size(current_database());') do |result|
|
data/spec/em_client_common.rb
CHANGED
@@ -106,6 +106,43 @@ end
|
|
106
106
|
|
107
107
|
shared_context 'em-pg common after' do
|
108
108
|
|
109
|
+
if described_class.single_row_mode?
|
110
|
+
|
111
|
+
it "should get each result in single row mode" do
|
112
|
+
@client.single_row_mode?.should be_true
|
113
|
+
@client.get_result_defer do |result|
|
114
|
+
result.should be_nil
|
115
|
+
@client.send_query('SELECT data, id FROM foo order by id')
|
116
|
+
@client.set_single_row_mode
|
117
|
+
EM::Iterator.new(@values, 1).map(proc{ |(data, id), iter|
|
118
|
+
@client.get_result_defer do |result|
|
119
|
+
result.should be_an_instance_of PG::Result
|
120
|
+
result.check
|
121
|
+
result.result_status.should eq PG::PGRES_SINGLE_TUPLE
|
122
|
+
value = result.to_a
|
123
|
+
value.should eq [{'data' => data, 'id' => id.to_s}]
|
124
|
+
result.clear
|
125
|
+
iter.return value
|
126
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
127
|
+
}, proc{ |results|
|
128
|
+
results.length.should eq @values.length
|
129
|
+
@client.get_result_defer do |result|
|
130
|
+
result.should be_an_instance_of PG::Result
|
131
|
+
result.check
|
132
|
+
result.result_status.should eq PG::PGRES_TUPLES_OK
|
133
|
+
result.to_a.should eq []
|
134
|
+
result.clear
|
135
|
+
@client.get_result_defer do |result|
|
136
|
+
result.should be_nil
|
137
|
+
EM.stop
|
138
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
139
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
140
|
+
})
|
141
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
109
146
|
it_should_execute("create prepared statement",
|
110
147
|
:prepare_defer, 'get_foo', 'SELECT * FROM foo order by id')
|
111
148
|
|
@@ -282,4 +319,44 @@ shared_context 'em-pg common after' do
|
|
282
319
|
end
|
283
320
|
end
|
284
321
|
end
|
322
|
+
|
323
|
+
it "should get last result asynchronously" do
|
324
|
+
@client.get_last_result_defer do |result|
|
325
|
+
result.should be_nil
|
326
|
+
@client.send_query('SELECT 1; SELECT 2; SELECT 3')
|
327
|
+
@client.get_last_result_defer do |result|
|
328
|
+
result.should be_an_instance_of PG::Result
|
329
|
+
result.getvalue(0,0).should eq '3'
|
330
|
+
result.clear
|
331
|
+
@client.get_last_result_defer do |result|
|
332
|
+
result.should be_nil
|
333
|
+
EM.stop
|
334
|
+
end
|
335
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
336
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
337
|
+
end
|
338
|
+
|
339
|
+
it "should get each result asynchronously" do
|
340
|
+
@client.get_result_defer do |result|
|
341
|
+
result.should be_nil
|
342
|
+
@client.send_query('SELECT 4; SELECT 5; SELECT 6')
|
343
|
+
EM::Iterator.new(%w[4 5 6], 1).map(proc{ |value, iter|
|
344
|
+
@client.get_result_defer do |result|
|
345
|
+
result.should be_an_instance_of PG::Result
|
346
|
+
result.check
|
347
|
+
result.result_status.should eq PG::PGRES_TUPLES_OK
|
348
|
+
result.getvalue(0,0).should eq value
|
349
|
+
result.clear
|
350
|
+
iter.return value
|
351
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
352
|
+
}, proc{ |results|
|
353
|
+
results.should eq %w[4 5 6]
|
354
|
+
@client.get_result_defer do |result|
|
355
|
+
result.should be_nil
|
356
|
+
EM.stop
|
357
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
358
|
+
})
|
359
|
+
end.should be_a_kind_of ::EM::DefaultDeferrable
|
360
|
+
end
|
361
|
+
|
285
362
|
end
|
data/spec/em_synchrony_client.rb
CHANGED
@@ -113,6 +113,33 @@ describe PG::EM::Client do
|
|
113
113
|
).should be_an_instance_of PG::Result
|
114
114
|
end
|
115
115
|
|
116
|
+
if described_class.single_row_mode?
|
117
|
+
|
118
|
+
it "should get each result in single row mode" do
|
119
|
+
@client.single_row_mode?.should be_true
|
120
|
+
@client.send_query('SELECT data, id FROM foo order by id')
|
121
|
+
@client.set_single_row_mode
|
122
|
+
@values.each do |data, id|
|
123
|
+
result = @client.get_result
|
124
|
+
result.should be_an_instance_of PG::Result
|
125
|
+
result.result_status.should eq PG::PGRES_SINGLE_TUPLE
|
126
|
+
result.check
|
127
|
+
value = result.to_a
|
128
|
+
result.clear
|
129
|
+
value.should eq [{'data' => data, 'id' => id.to_s}]
|
130
|
+
end
|
131
|
+
result = @client.get_result
|
132
|
+
result.should be_an_instance_of PG::Result
|
133
|
+
result.check
|
134
|
+
result.result_status.should eq PG::PGRES_TUPLES_OK
|
135
|
+
result.to_a.should eq []
|
136
|
+
result.clear
|
137
|
+
@client.get_result.should be_nil
|
138
|
+
EM.stop
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
116
143
|
it "should connect to database asynchronously" do
|
117
144
|
this = :first
|
118
145
|
Encoding.default_internal = Encoding::ISO_8859_1
|
@@ -149,12 +176,12 @@ describe PG::EM::Client do
|
|
149
176
|
f = Fiber.current
|
150
177
|
Fiber.new do
|
151
178
|
begin
|
152
|
-
described_class.new
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
179
|
+
conn = described_class.new
|
180
|
+
this = :second
|
181
|
+
Encoding.default_internal = nil
|
182
|
+
conn.should be_an_instance_of described_class
|
183
|
+
conn.external_encoding.should be conn.internal_encoding
|
184
|
+
conn.finish
|
158
185
|
ensure
|
159
186
|
f.resume
|
160
187
|
end
|
@@ -256,18 +283,59 @@ describe PG::EM::Client do
|
|
256
283
|
|
257
284
|
it "should not expire after executing erraneous query" do
|
258
285
|
@client.query_timeout.should eq 0
|
259
|
-
@client.query_timeout =
|
260
|
-
@client.query_timeout.should eq
|
286
|
+
@client.query_timeout = 1
|
287
|
+
@client.query_timeout.should eq 1
|
261
288
|
expect {
|
262
289
|
@client.query('SELLECT 1')
|
263
290
|
}.to raise_error(PG::SyntaxError, /syntax error/)
|
264
291
|
@client.async_command_aborted.should be_false
|
265
292
|
@client.status.should be PG::CONNECTION_OK
|
266
|
-
::EM::Synchrony.sleep
|
293
|
+
::EM::Synchrony.sleep 1.5
|
267
294
|
@client.async_command_aborted.should be_false
|
268
295
|
@client.status.should be PG::CONNECTION_OK
|
269
296
|
end
|
270
297
|
|
298
|
+
it "should get last result asynchronously" do
|
299
|
+
result = @client.get_last_result
|
300
|
+
result.should be_nil
|
301
|
+
@client.get_last_result.should be_nil
|
302
|
+
@client.send_query('SELECT 1; SELECT 2; SELECT 3')
|
303
|
+
asynchronous = false
|
304
|
+
EM.next_tick { asynchronous = true }
|
305
|
+
result = @client.get_last_result
|
306
|
+
result.should be_an_instance_of PG::Result
|
307
|
+
result.getvalue(0,0).should eq '3'
|
308
|
+
result.clear
|
309
|
+
@client.get_last_result.should be_nil
|
310
|
+
asynchronous.should be true
|
311
|
+
end
|
312
|
+
|
313
|
+
it "should get each result asynchronously" do
|
314
|
+
result = @client.get_result
|
315
|
+
result.should be_nil
|
316
|
+
@client.get_result do |result|
|
317
|
+
result.should be_nil
|
318
|
+
end.should be_nil
|
319
|
+
@client.send_query('SELECT 4,pg_sleep(0.1); SELECT 5; SELECT 6')
|
320
|
+
asynchronous = false
|
321
|
+
EM.next_tick { asynchronous = true }
|
322
|
+
%w[4 5 6].map do |value|
|
323
|
+
result = @client.get_result do |result|
|
324
|
+
result.should be_an_instance_of PG::Result
|
325
|
+
result.check
|
326
|
+
result.result_status.should eq PG::PGRES_TUPLES_OK
|
327
|
+
result.getvalue(0,0).should eq value
|
328
|
+
result
|
329
|
+
end
|
330
|
+
expect do
|
331
|
+
result.clear
|
332
|
+
end.to raise_error PG::Error, /cleared/
|
333
|
+
value
|
334
|
+
end.should eq %w[4 5 6]
|
335
|
+
@client.get_result.should be_nil
|
336
|
+
asynchronous.should be true
|
337
|
+
end
|
338
|
+
|
271
339
|
describe 'PG::EM::Client#transaction' do
|
272
340
|
|
273
341
|
it "should raise ArgumentError when there is no block" do
|