em-pg-client 0.2.0.pre.3 → 0.2.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/BENCHMARKS.rdoc +1 -1
- data/HISTORY.rdoc +10 -0
- data/README.rdoc +189 -52
- data/em-pg-client.gemspec +2 -2
- data/lib/em-synchrony/pg.rb +32 -5
- data/lib/pg/em.rb +140 -70
- data/spec/em_client_autoreconnect.rb +4 -2
- data/spec/em_client_common.rb +191 -65
- data/spec/em_devel_client.rb +3 -0
- data/spec/em_release_client.rb +3 -0
- data/spec/em_synchrony_client.rb +130 -21
- data/spec/em_synchrony_client_autoreconnect.rb +4 -2
- metadata +82 -61
data/BENCHMARKS.rdoc
CHANGED
@@ -6,7 +6,7 @@ The goal of the test is simply to retrieve (~80000) rows from table with a lot o
|
|
6
6
|
The parallel method uses synchrony for simplicity.
|
7
7
|
|
8
8
|
* +single+ is (eventmachine-less) job for retrieving a whole data table in
|
9
|
-
one
|
9
|
+
one simple query "select * from resources"
|
10
10
|
* +parallel+ chunk_row_count / concurrency] uses em-pg-client for retrieving
|
11
11
|
result in chunks by +chunk_row_count+ rows and using +concurrency+ parallel
|
12
12
|
connections
|
data/HISTORY.rdoc
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
0.2.0
|
2
|
+
- disabled async_autoreconnect by default unless on_autoreconnect is set
|
3
|
+
- async_connect sets #internal_encoding to Encoding.default_internal
|
4
|
+
- fix: finish connection on async connect_timeout
|
5
|
+
- nice errors generated on missing dependencies
|
6
|
+
- blocking #reset() should clear async_command_aborted flag
|
7
|
+
- less calls to #is_busy in Watcher#notify_readable
|
8
|
+
- #async_describe_portal + specs
|
9
|
+
- #async_describe_prepared + specs
|
10
|
+
|
1
11
|
0.2.0.pre.3
|
2
12
|
- #status() returns CONNECTION_BAD for connections with expired query
|
3
13
|
- spec: query timeout expiration
|
data/README.rdoc
CHANGED
@@ -6,102 +6,111 @@ Author:: Rafał Michalski (mailto:rafal@yeondir.com)
|
|
6
6
|
|
7
7
|
== DESCRIPTION
|
8
8
|
|
9
|
-
*em-pg-client* is
|
10
|
-
based on ruby-pg[https://bitbucket.org/ged/ruby-pg]
|
9
|
+
*em-pg-client* is the Ruby and EventMachine driver interface to the PostgreSQL
|
10
|
+
RDBMS. It is based on ruby-pg[https://bitbucket.org/ged/ruby-pg].
|
11
11
|
|
12
12
|
== FEATURES
|
13
13
|
|
14
|
-
*
|
15
|
-
* fully async auto
|
16
|
-
*
|
17
|
-
*
|
14
|
+
* Non-blocking / asynchronous processing with EventMachine,
|
15
|
+
* fully async auto re-connects on connection losses (e.g.: RDBMS restarts),
|
16
|
+
* minimal changes to PG::Connection[http://deveiate.org/code/pg/PG/Connection.html] API,
|
17
|
+
* configurable timeouts (connect or execute) of asynchronous processing,
|
18
|
+
* additional Fiber-aware version supporting EM-Synchrony[https://github.com/igrigorik/em-synchrony].
|
18
19
|
|
19
20
|
== BUGS/LIMITATIONS
|
20
21
|
|
22
|
+
* no async support for: COPY commands (+get_copy_data+, +put_copy_data+),
|
23
|
+
+wait_for_notify+ and +transaction+
|
21
24
|
* actually no ActiveRecord nor Sequel support (you are welcome to contribute).
|
25
|
+
* doesn't work on Windows (issue #7)
|
22
26
|
|
23
|
-
== API Changes
|
27
|
+
== API Changes between versions
|
24
28
|
|
29
|
+
=== 0.1.x -> 0.2.x
|
25
30
|
* +on_reconnect+ renamed to more accurate +on_autoreconnect+
|
26
|
-
(well, it's not used by
|
31
|
+
(well, it's not used by PG::EM::Client#reset call).
|
32
|
+
* +async_autoreconnect+ is +false+ by default if +on_autoreconnect+
|
33
|
+
is *not* specified as initialization option.
|
27
34
|
|
28
35
|
== TODO:
|
29
36
|
|
37
|
+
* implement EM adapted version of +get_copy_data+, +put_copy_data+,
|
38
|
+
+wait_for_notify+ and +transaction+
|
39
|
+
* add some fd/socket hackery to get it working on Windows (issue #7)
|
30
40
|
* em-synchrony ORM (ActiveRecord, Sequel and maybe Datamapper) support
|
31
41
|
as separate projects
|
42
|
+
* present more benchmarks
|
32
43
|
|
33
44
|
== REQUIREMENTS
|
34
45
|
|
35
|
-
* ruby >= 1.9
|
36
|
-
* https://bitbucket.org/ged/ruby-pg
|
37
|
-
* http://
|
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
|
48
|
+
* PostgreSQL[http://www.postgresql.org/ftp/source/] RDBMS >= 8.3
|
49
|
+
* http://rubyeventmachine.com >= 0.12.10
|
38
50
|
* (optional) EM-Synchrony[https://github.com/igrigorik/em-synchrony]
|
39
51
|
|
40
52
|
== INSTALL
|
41
53
|
|
42
|
-
=== Legacy
|
43
|
-
|
44
54
|
$ [sudo] gem install em-pg-client
|
45
|
-
|
46
|
-
==== Gemfile
|
47
|
-
|
48
|
-
# eventmachine
|
49
|
-
gem "em-pg-client", "~> 0.1.1", :require => 'pg/em'
|
50
|
-
# em-synchrony
|
51
|
-
gem "em-pg-client", "~> 0.1.1", :require => ['pg/em', 'em-synchrony/pg']
|
52
|
-
|
53
|
-
=== Latest branch (fully-async)
|
54
|
-
|
55
|
-
$ [sudo] gem install em-pg-client --pre
|
56
55
|
|
57
56
|
==== Gemfile
|
58
57
|
|
59
58
|
# eventmachine
|
60
|
-
gem "em-pg-client", "~> 0.2.0
|
59
|
+
gem "em-pg-client", "~> 0.2.0", :require => 'pg/em'
|
61
60
|
# em-synchrony
|
62
|
-
gem "em-pg-client", "~> 0.2.0
|
61
|
+
gem "em-pg-client", "~> 0.2.0", :require => ['pg/em', 'em-synchrony/pg']
|
63
62
|
|
64
63
|
==== Github
|
65
64
|
|
66
65
|
git clone git://github.com/royaltm/ruby-em-pg-client.git
|
67
|
-
git checkout fully-async
|
68
66
|
|
69
67
|
== WHY?
|
70
68
|
|
71
|
-
Because
|
69
|
+
Because I didn't find any ruby-pg's EM implementation to fit my needs.
|
72
70
|
I've found at least 3 other implementations of EM postgres client:
|
73
71
|
|
74
72
|
* https://github.com/jzimmek/em-postgresql-sequel
|
75
73
|
* https://github.com/leftbee/em-postgresql-adapter
|
76
74
|
* https://github.com/jtoy/em-postgres
|
77
75
|
|
78
|
-
and (except the bundled one which uses no longer maintained postgres-pr library)
|
76
|
+
and (except the EM-bundled one which uses no longer maintained postgres-pr library)
|
79
77
|
all of them have similiar flaws:
|
80
78
|
|
81
|
-
* 2 of them are designed to support some ORM (ActiveRecord or Sequel)
|
79
|
+
* 2 of them are designed to support some ORM (ActiveRecord or Sequel),
|
82
80
|
so they are EM-Synchrony only,
|
83
81
|
* non-standard API method names,
|
84
82
|
* no (nonexistent or non-working) autoreconnect implementation,
|
83
|
+
* poor error handling,
|
85
84
|
* not fully supporting asynchronous PG::Connection API.
|
86
85
|
|
87
86
|
The last one is worth some comment:
|
88
87
|
|
89
88
|
They all use blocking methods to retrieve whole result from server
|
90
|
-
(PGConn#block
|
89
|
+
(PGConn#block[http://deveiate.org/code/pg/PG/Connection.html#method-i-block] or
|
90
|
+
PGConn#get_result[http://deveiate.org/code/pg/PG/Connection.html#method-i-get_result] which also
|
91
91
|
blocks when there is not enough buffered data on socket).
|
92
92
|
|
93
|
-
This implementation makes use of non-blocking:
|
94
|
-
|
95
|
-
|
93
|
+
This implementation makes use of non-blocking:
|
94
|
+
PGConn#is_busy[http://deveiate.org/code/pg/PG/Connection.html#method-i-is_busy] and
|
95
|
+
PGConn#consume_input[http://deveiate.org/code/pg/PG/Connection.html#method-i-consume_input] methods.
|
96
|
+
Depending on the size of queries results and the level of concurrency, the gain in overall speed and
|
97
|
+
responsiveness of your application might be actually quite huge. I've done some
|
98
|
+
tests[link:BENCHMARKS.rdoc] already.
|
96
99
|
|
97
100
|
== Thanks
|
98
101
|
|
99
102
|
The greetz go to:
|
100
103
|
- Authors[https://bitbucket.org/ged/ruby-pg/wiki/Home#!copying] of +pg+ driver (especially for its async-api)
|
101
104
|
- Francis Cianfrocca for great reactor framework (EventMachine[https://github.com/eventmachine/eventmachine])
|
102
|
-
- Ilya Grigorik (igrigorik[https://github.com/igrigorik]) for (untangling
|
105
|
+
- Ilya Grigorik (igrigorik[https://github.com/igrigorik]) for (untangling[http://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers/]) EM with Fibers
|
103
106
|
|
104
107
|
== USAGE
|
108
|
+
+em-pg-client+ provides PG::EM::Client class which inherits
|
109
|
+
PG::Connection[http://deveiate.org/code/pg/PG/Connection.html].
|
110
|
+
You can work with PG::EM::Client almost the same way you would with
|
111
|
+
PG::Connection.
|
112
|
+
|
113
|
+
The real difference begins when you turn EventMachine reactor on.
|
105
114
|
|
106
115
|
=== BASIC
|
107
116
|
|
@@ -109,13 +118,26 @@ The greetz go to:
|
|
109
118
|
|
110
119
|
# no async
|
111
120
|
pg = PG::EM::Client.new dbname: 'test'
|
112
|
-
|
121
|
+
pg.query('select * from foo') do |result|
|
113
122
|
puts Array(result).inspect
|
114
123
|
end
|
115
|
-
|
124
|
+
|
116
125
|
# asynchronous
|
117
126
|
EM.run do
|
118
|
-
|
127
|
+
df = pg.query('select * from foo')
|
128
|
+
df.callback { |result|
|
129
|
+
puts Array(result).inspect
|
130
|
+
EM.stop
|
131
|
+
}
|
132
|
+
df.errback {|ex|
|
133
|
+
raise ex
|
134
|
+
}
|
135
|
+
puts "sent"
|
136
|
+
end
|
137
|
+
|
138
|
+
# alternatively
|
139
|
+
EM.run do
|
140
|
+
pg.query('select * from foo') do |result|
|
119
141
|
raise result if result.is_a? ::Exception
|
120
142
|
puts Array(result).inspect
|
121
143
|
EM.stop
|
@@ -123,12 +145,79 @@ The greetz go to:
|
|
123
145
|
puts "sent"
|
124
146
|
end
|
125
147
|
|
148
|
+
=== PG::Connection methods adapted to EventMachine
|
149
|
+
The list of PG::EM::Client async methods for processing with EventMachine.
|
150
|
+
|
151
|
+
==== 1. Async methods (always returning +Deferrable+ object):
|
152
|
+
|
153
|
+
* +Client.async_connect+ (singleton)
|
154
|
+
* +async_reset+
|
155
|
+
* +async_exec+ (alias: +async_query+)
|
156
|
+
* +async_prepare+
|
157
|
+
* +async_exec_prepared+
|
158
|
+
* +async_describe_prepared+
|
159
|
+
* +async_describe_portal+
|
160
|
+
|
161
|
+
For arguments of theese methods consult their original blocking (without +async_+ prefix)
|
162
|
+
counterparts in PG::Connection[http://deveiate.org/code/pg/PG/Connection.html] manual.
|
163
|
+
|
164
|
+
Use +callback+ on the returned +Deferrable+ to receive result.
|
165
|
+
The result you receive is PG::EM::Client for PG::EM::Client.async_connect
|
166
|
+
and +async_reset+, and PG::Result[http://deveiate.org/code/pg/PG/Result.html] for the rest
|
167
|
+
of the methods. The received PG::EM::Client is in a connected state and ready for queries.
|
168
|
+
You need to +clear+ obtained PG::Result object yourself or leave it to +gc+.
|
169
|
+
|
170
|
+
To detect a failure in an executed method use +errback+ on returned +Deferrable+.
|
171
|
+
You should expect an instance of +Exception+ (usually PG::Error) as +errback+
|
172
|
+
argument. You may check its +backtrace+ to find origin of the error.
|
173
|
+
|
174
|
+
==== 2. Async / blocking methods (returning +Deferrable+ only when EM is running):
|
175
|
+
|
176
|
+
* +exec+ (alias: +query+)
|
177
|
+
* +prepare+
|
178
|
+
* +exec_prepared+
|
179
|
+
* +describe_prepared+
|
180
|
+
* +describe_portal+
|
181
|
+
|
182
|
+
Outside EventMachine's event loop these methods are regular, blocking PG::Connection
|
183
|
+
methods.
|
184
|
+
|
185
|
+
All the methods (1 & 2) accept block argument which they attach to +callback+ and +errback+
|
186
|
+
hooks of returned +Deferrable+.
|
187
|
+
|
188
|
+
You may also mix async and blocking methods without closing the connection.
|
189
|
+
You only need to start/stop EventMachine in between async calls.
|
190
|
+
|
191
|
+
==== Special options
|
192
|
+
There are 3 additional connection options and 1 standard +pg+ option used by
|
193
|
+
async methods. You may add them as one of the *hash* options to
|
194
|
+
PG::EM::Client.new or PG::EM::Client.async_connect or simply use accessor
|
195
|
+
methods to change them on the fly. The additional options are not passed to
|
196
|
+
+libpq+.
|
197
|
+
|
198
|
+
The options are:
|
199
|
+
|
200
|
+
- +async_autoreconnect+ (+true+ / +false+ with default +false+ unless
|
201
|
+
+on_autoreconnect+ is specified)
|
202
|
+
allows automatic re-connection when there was a problem with connection
|
203
|
+
to the server,
|
204
|
+
- +on_autoreconnect+ (+nil+ / +Proc+ with default +nil+)
|
205
|
+
a hook which is called after auto-reconnecting,
|
206
|
+
- +query_timeout+ (+Float+ / +Fixnum+ with default +0+)
|
207
|
+
allows to set timeout for query execution,
|
208
|
+
- +connect_timeout+ (+Float+ / +Fixnum+ with default +0+)
|
209
|
+
connection establishing and resetting timeout.
|
210
|
+
|
211
|
+
Only +connect_timeout+ is a standard +libpq+ option, although changing it by
|
212
|
+
accessor method only affects asynchronous functions.
|
213
|
+
|
126
214
|
=== AUTORECONNECTING IN ASYNC MODE
|
127
|
-
Autoreconnecting is done in non-blocking manner using
|
215
|
+
Autoreconnecting is done in non-blocking manner using +async_reset+ internally.
|
128
216
|
|
129
217
|
EM.run do
|
130
218
|
pg = PG::EM::Client.new dbname: 'test',
|
131
|
-
connect_timeout: 5, query_timeout: 50
|
219
|
+
connect_timeout: 5, query_timeout: 50,
|
220
|
+
async_autoreconnect: true
|
132
221
|
try_query = lambda do |&blk|
|
133
222
|
pg.query('select * from foo') do |result|
|
134
223
|
raise result if result.is_a? ::Exception
|
@@ -143,21 +232,22 @@ Autoreconnecting is done in non-blocking manner using #async_reset internally.
|
|
143
232
|
}
|
144
233
|
end
|
145
234
|
|
146
|
-
to
|
235
|
+
to enable this feature call:
|
147
236
|
|
148
|
-
pg.async_autoreconnect =
|
237
|
+
pg.async_autoreconnect = true
|
149
238
|
|
150
239
|
or
|
151
240
|
|
152
241
|
pg = PG::EM::Client.new dbname: 'test',
|
153
|
-
async_autoreconnect:
|
242
|
+
async_autoreconnect: true
|
154
243
|
|
155
244
|
It's also possible to define +on_autoreconnect+ callback to be invoked
|
156
245
|
while the connection has been reset. It's called just before the send query
|
157
246
|
command is executed:
|
158
247
|
|
159
248
|
EM.run do
|
160
|
-
pg = PG::EM::Client.new dbname: 'test'
|
249
|
+
pg = PG::EM::Client.new dbname: 'test',
|
250
|
+
async_autoreconnect: true
|
161
251
|
pg.prepare('bar', 'select * from foo order by cdate desc') do
|
162
252
|
pg.on_autoreconnect = proc { |c, e|
|
163
253
|
c.prepare('bar', 'select * from foo order by cdate desc')
|
@@ -177,14 +267,15 @@ command is executed:
|
|
177
267
|
end
|
178
268
|
end
|
179
269
|
|
180
|
-
As you can see it's possible to send async query from inside on_autoreconnect
|
270
|
+
As you can see it's possible to send async query from inside +on_autoreconnect+
|
181
271
|
proc. However you have to pass +Deferrable+ from the async callback to the
|
182
|
-
caller. See
|
272
|
+
caller. See PG::EM::Client#on_autoreconnect docs for details.
|
183
273
|
|
184
274
|
=== TRUE ASYNC
|
185
|
-
For non-blocking connect use PG::EM::Client.async_connect and
|
186
|
-
asynchronous
|
187
|
-
|
275
|
+
For non-blocking connect use PG::EM::Client.async_connect and
|
276
|
+
PG::EM::Client#async_reset for asynchronous re-connect. Like other async
|
277
|
+
methods they return +Deferrable+ object.
|
278
|
+
Use Deferrable's #callback to obtain already connected PG::EM::Client.
|
188
279
|
|
189
280
|
EM.run do
|
190
281
|
pool = (1..10).map {
|
@@ -205,10 +296,16 @@ Use #callback to obtain already connected Client.
|
|
205
296
|
end
|
206
297
|
end
|
207
298
|
|
208
|
-
=== EM-Synchrony
|
209
|
-
|
210
|
-
|
299
|
+
=== Fibers / EM-Synchrony
|
300
|
+
There is a special version of PG::EM::Client library with fiber aware methods
|
301
|
+
for EM-Synchrony or other implementations of Fiber untangled EventMachine.
|
302
|
+
|
303
|
+
The +require+ string is "em-synchrony/pg" instead of "pg/em".
|
304
|
+
|
305
|
+
+em-synchrony/pg+ version of PG::EM::Client.new is fully asynchronous and
|
306
|
+
blocks only current fiber. This also applies to PG::EM::Client#reset.
|
211
307
|
|
308
|
+
require 'em-synchrony'
|
212
309
|
require 'em-synchrony/pg'
|
213
310
|
|
214
311
|
EM.synchrony do
|
@@ -219,6 +316,43 @@ This also applies to #reset.
|
|
219
316
|
EM.stop
|
220
317
|
end
|
221
318
|
|
319
|
+
Although em-synchrony[https://github.com/igrigorik/em-synchrony/] provides
|
320
|
+
very nice set of tools for untangled EventMachine, you don't really require
|
321
|
+
it to fully benefit from this version of PG::EM::Client.
|
322
|
+
|
323
|
+
==== PG::Connection methods adapted to EM-Synchrony
|
324
|
+
The list of PG::EM::Client fiber aware methods for processing with
|
325
|
+
EM-Synchrony / EventMachine.
|
326
|
+
|
327
|
+
All +async_*+ methods are exactly the same as in pure EventMachine version
|
328
|
+
of PG::EM::Client.
|
329
|
+
|
330
|
+
The fiber aware methods are:
|
331
|
+
|
332
|
+
* +Client.connect+ (singleton, alias: +new+, +open+, +setdb+, +setdblogin+)
|
333
|
+
* +reset+
|
334
|
+
* +exec+ (alias: +query+)
|
335
|
+
* +prepare+
|
336
|
+
* +exec_prepared+
|
337
|
+
* +describe_prepared+
|
338
|
+
* +describe_portal+
|
339
|
+
|
340
|
+
Under the hood, these methods call async counterparts of themselves and +yield+ from current
|
341
|
+
fiber awaiting for the result. The PG::Result (or PG::EM::Client for +connect+
|
342
|
+
and +reset+) is then returned to the caller. If code block was given, it is
|
343
|
+
executed with result as the argument. In that case the value of the block is
|
344
|
+
returned instead and PG::Result is cleared (or in case of +connect+ or +reset+
|
345
|
+
PG::EM::Client is being closed) after executing block. From single fiber point
|
346
|
+
of view, they behave like regular blocking PG::Connection methods.
|
347
|
+
|
348
|
+
Each of them is also automatic, detecting if EventMachine is running.
|
349
|
+
If called outside EM event loop they are exactly the original methods of
|
350
|
+
PG::Connection.
|
351
|
+
|
352
|
+
Like in pure EventMachine version you can mix async, fiber aware and
|
353
|
+
blocking methods without finishing the connection. You only need to
|
354
|
+
start/stop EventMachine in between async calls.
|
355
|
+
|
222
356
|
==== Handling errors
|
223
357
|
|
224
358
|
EM.synchrony do
|
@@ -289,6 +423,9 @@ This also applies to #reset.
|
|
289
423
|
EM.stop
|
290
424
|
end
|
291
425
|
|
426
|
+
Specifying +on_autoreconnect+ as PG::EM::Client.new initialization option,
|
427
|
+
implicitly enables +async_autoreconnect+.
|
428
|
+
|
292
429
|
== LICENCE
|
293
430
|
|
294
431
|
The MIT License - Copyright (c) 2012 Rafał Michalski
|
data/em-pg-client.gemspec
CHANGED
@@ -2,14 +2,14 @@ $:.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.0"
|
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"
|
9
9
|
s.email = "rafal@yeondir.com"
|
10
10
|
s.homepage = "http://github.com/royaltm/ruby-em-pg-client"
|
11
11
|
s.require_path = "lib"
|
12
|
-
s.description = "PostgreSQL asynchronous EventMachine client (
|
12
|
+
s.description = "PostgreSQL asynchronous EventMachine client, based on pg interface (PG::Connection)"
|
13
13
|
s.authors = ["Rafal Michalski"]
|
14
14
|
s.files = `git ls-files`.split("\n") - ['.gitignore']
|
15
15
|
s.test_files = Dir.glob("spec/**/*")
|
data/lib/em-synchrony/pg.rb
CHANGED
@@ -5,18 +5,41 @@ module PG
|
|
5
5
|
# Author:: Rafal Michalski (mailto:royaltm75@gmail.com)
|
6
6
|
# Licence:: MIT License
|
7
7
|
#
|
8
|
-
# =PostgreSQL Client for EM-Synchrony
|
8
|
+
# =PostgreSQL Client for EM-Synchrony/Fibered EventMachine
|
9
9
|
#
|
10
10
|
|
11
11
|
# conform to *standard*
|
12
12
|
alias_method :aquery, :async_query
|
13
13
|
|
14
|
-
# fiber
|
14
|
+
# fiber aware methods:
|
15
15
|
# - exec (aliased as query)
|
16
16
|
# - exec_prepared
|
17
17
|
# - prepare
|
18
|
-
|
18
|
+
# - describe_prepared
|
19
|
+
# - describe_portal
|
20
|
+
# - reset
|
21
|
+
# - Client.connect
|
22
|
+
%w(exec
|
23
|
+
exec_prepared
|
24
|
+
prepare
|
25
|
+
describe_prepared
|
26
|
+
describe_portal
|
27
|
+
reset
|
28
|
+
self.connect).each do |name|
|
19
29
|
async_name = "async_#{name.split('.').last}"
|
30
|
+
blocking_call = case name
|
31
|
+
when 'reset'
|
32
|
+
'@async_command_aborted = false
|
33
|
+
super(*args, &blk)'
|
34
|
+
else
|
35
|
+
'super(*args, &blk)'
|
36
|
+
end
|
37
|
+
clear_method = case name
|
38
|
+
when 'reset', 'self.connect'
|
39
|
+
'finish'
|
40
|
+
else
|
41
|
+
'clear'
|
42
|
+
end
|
20
43
|
class_eval <<-EOD
|
21
44
|
def #{name}(*args, &blk)
|
22
45
|
if ::EM.reactor_running?
|
@@ -28,12 +51,16 @@ module PG
|
|
28
51
|
result = Fiber.yield
|
29
52
|
raise result if result.is_a?(::Exception)
|
30
53
|
if block_given?
|
31
|
-
|
54
|
+
begin
|
55
|
+
yield result
|
56
|
+
ensure
|
57
|
+
result.#{clear_method}
|
58
|
+
end
|
32
59
|
else
|
33
60
|
result
|
34
61
|
end
|
35
62
|
else
|
36
|
-
|
63
|
+
#{blocking_call}
|
37
64
|
end
|
38
65
|
end
|
39
66
|
EOD
|