em-postgres 0.0.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/README +12 -0
- data/Rakefile +19 -0
- data/em-postgres.gemspec +24 -0
- data/lib/em-postgres.rb +7 -0
- data/lib/em-postgres/connection.rb +224 -0
- data/lib/em-postgres/postgres.rb +143 -0
- data/spec/helper.rb +6 -0
- data/spec/postgres_spec.rb +155 -0
- metadata +85 -0
data/README
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Async PostgreSQL driver for Ruby/EventMachine
|
2
|
+
based off Aman Gupta's mysql driver
|
3
|
+
|
4
|
+
|
5
|
+
Requires pg
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
TODOS:
|
10
|
+
get a working java driver
|
11
|
+
ability to use different MRI postgres drivers (postgres-pr, pg, postgres)
|
12
|
+
add working adaptors for activerecord and sequel
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'jeweler'
|
5
|
+
Jeweler::Tasks.new do |gemspec|
|
6
|
+
gemspec.name = "em-postgres"
|
7
|
+
gemspec.summary = "Async PostgreSQL driver for Ruby/Eventmachine"
|
8
|
+
gemspec.description = gemspec.summary
|
9
|
+
gemspec.email = "jtoy@jtoy.net"
|
10
|
+
gemspec.homepage = "http://github.com/jtoy/em-postgres"
|
11
|
+
gemspec.authors = ["Jason Toy"]
|
12
|
+
gemspec.add_dependency('eventmachine', '>= 0.12.9')
|
13
|
+
gemspec.rubyforge_project = "em-postgres"
|
14
|
+
end
|
15
|
+
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
19
|
+
end
|
data/em-postgres.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
spec = Gem::Specification.new do |s|
|
2
|
+
s.name = 'em-postgres'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.date = '2011-08-25'
|
5
|
+
s.summary = 'Async PostgreSQL client API for Ruby/EventMachine'
|
6
|
+
s.email = "jtoy@jtoy.net"
|
7
|
+
s.homepage = "http://github.com/jtoy/em-postgres"
|
8
|
+
s.description = 'Async PostgreSQL client API for Ruby/EventMachine'
|
9
|
+
s.has_rdoc = false
|
10
|
+
s.authors = ["Jason Toy"]
|
11
|
+
s.add_dependency('eventmachine', '>= 0.12.9')
|
12
|
+
|
13
|
+
# git ls-files
|
14
|
+
s.files = %w[
|
15
|
+
README
|
16
|
+
Rakefile
|
17
|
+
em-postgres.gemspec
|
18
|
+
lib/em-postgres/postgres.rb
|
19
|
+
lib/em-postgres/connection.rb
|
20
|
+
lib/em-postgres.rb
|
21
|
+
spec/helper.rb
|
22
|
+
spec/postgres_spec.rb
|
23
|
+
]
|
24
|
+
end
|
data/lib/em-postgres.rb
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
|
2
|
+
class Postgres
|
3
|
+
def result
|
4
|
+
@cur_result
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
module EventMachine
|
9
|
+
class PostgresConnection < EventMachine::Connection
|
10
|
+
|
11
|
+
attr_reader :processing, :connected, :opts
|
12
|
+
alias :settings :opts
|
13
|
+
|
14
|
+
MAX_RETRIES_ON_DEADLOCKS = 10
|
15
|
+
|
16
|
+
DisconnectErrors = [
|
17
|
+
'query: not connected',
|
18
|
+
'Postgres server has gone away',
|
19
|
+
'Lost connection to Postgres server during query'
|
20
|
+
] unless defined? DisconnectErrors
|
21
|
+
|
22
|
+
def initialize(postgres,opts,conn)
|
23
|
+
#def initialize(postgres,opts)
|
24
|
+
|
25
|
+
begin
|
26
|
+
@conn = conn
|
27
|
+
@postgres = postgres
|
28
|
+
@fd = postgres.socket
|
29
|
+
@opts = opts
|
30
|
+
@current = nil
|
31
|
+
@queue = []
|
32
|
+
@processing = false
|
33
|
+
@connected = true
|
34
|
+
|
35
|
+
self.notify_readable = true
|
36
|
+
EM.add_timer(0){ next_query }
|
37
|
+
rescue => e
|
38
|
+
puts e.inspect
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.connect(opts)
|
43
|
+
if conn = connect_socket(opts)
|
44
|
+
#debug [:connect, conn.socket, opts]
|
45
|
+
EM.watch(conn.socket, EventMachine::PostgresConnection,conn,opts)
|
46
|
+
else
|
47
|
+
# invokes :errback callback in opts before firing again
|
48
|
+
debug [:reconnect]
|
49
|
+
EM.add_timer(5) { connect opts }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# stolen from sequel
|
54
|
+
def self.connect_socket(opts)
|
55
|
+
begin
|
56
|
+
conn = PGconn.connect(
|
57
|
+
opts[:host],
|
58
|
+
(opts[:port]), #TODO deal with host and port
|
59
|
+
nil,nil,
|
60
|
+
opts[:database],
|
61
|
+
opts[:user],
|
62
|
+
opts[:password]
|
63
|
+
)
|
64
|
+
# set encoding _before_ connecting
|
65
|
+
if encoding = opts[:encoding] || opts[:charset]
|
66
|
+
if conn.respond_to?(:set_client_encoding)
|
67
|
+
conn.set_client_encoding(encoding)
|
68
|
+
else
|
69
|
+
conn.async_exec("set client_encoding to '#{encoding}'")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
conn
|
73
|
+
rescue Exception => e
|
74
|
+
puts "#{e} exception"
|
75
|
+
if cb = opts[:errback]
|
76
|
+
cb.call(e)
|
77
|
+
nil
|
78
|
+
else
|
79
|
+
raise e
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def notify_readable
|
85
|
+
if item = @current
|
86
|
+
sql, cblk, eblk, retries = item
|
87
|
+
#results = []
|
88
|
+
#result = nil
|
89
|
+
#@postgres.get_result{|r| result = r}
|
90
|
+
#@postgres.get_result #TODO remove this, I can't process anymore code without this.
|
91
|
+
result = nil
|
92
|
+
loop do
|
93
|
+
# Fetch the next result. If there isn't one, the query is
|
94
|
+
# finished
|
95
|
+
item = @postgres.get_result
|
96
|
+
if item
|
97
|
+
result = item
|
98
|
+
else
|
99
|
+
break
|
100
|
+
end
|
101
|
+
#puts "\n\nQuery result:\n%p\n" % [ result.values ]
|
102
|
+
end
|
103
|
+
|
104
|
+
unless @postgres.error_message == ""
|
105
|
+
#TODO this is wrong
|
106
|
+
eb = (eblk || @opts[:on_error])
|
107
|
+
eb.call(result) if eb
|
108
|
+
result.clear
|
109
|
+
#reconnect
|
110
|
+
@processing = false
|
111
|
+
#@current = nil
|
112
|
+
return next_query
|
113
|
+
end
|
114
|
+
# kick off next query in the background
|
115
|
+
# as we process the current results
|
116
|
+
@current = nil
|
117
|
+
@processing = false
|
118
|
+
cblk.call(result) if cblk
|
119
|
+
result.clear
|
120
|
+
next_query
|
121
|
+
else
|
122
|
+
return close
|
123
|
+
end
|
124
|
+
|
125
|
+
rescue Exception => e
|
126
|
+
puts "error #{e}"
|
127
|
+
if e.message =~ /Deadlock/ and retries < MAX_RETRIES_ON_DEADLOCKS
|
128
|
+
@queue << [sql, cblk, eblk, retries + 1]
|
129
|
+
@processing = false
|
130
|
+
next_query
|
131
|
+
|
132
|
+
elsif DisconnectErrors.include? e.message
|
133
|
+
@queue << [sql, cblk, eblk, retries + 1]
|
134
|
+
return #close
|
135
|
+
|
136
|
+
elsif cb = (eblk || @opts[:on_error])
|
137
|
+
cb.call(e)
|
138
|
+
@processing = false
|
139
|
+
next_query
|
140
|
+
|
141
|
+
else
|
142
|
+
raise e
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def unbind
|
147
|
+
|
148
|
+
# wait for the next tick until the current fd is removed completely from the reactor
|
149
|
+
#
|
150
|
+
# in certain cases the new FD# (@mysql.socket) is the same as the old, since FDs are re-used
|
151
|
+
# without next_tick in these cases, unbind will get fired on the newly attached signature as well
|
152
|
+
#
|
153
|
+
# do _NOT_ use EM.next_tick here. if a bunch of sockets disconnect at the same time, we want
|
154
|
+
# reconnects to happen after all the unbinds have been processed
|
155
|
+
|
156
|
+
#@connected = false
|
157
|
+
EM.next_tick { reconnect }
|
158
|
+
end
|
159
|
+
|
160
|
+
def reconnect
|
161
|
+
puts "DDDDD"
|
162
|
+
@processing = false
|
163
|
+
@postgres = @conn.connect_socket(@opts)
|
164
|
+
@fd = @postgres.socket
|
165
|
+
|
166
|
+
@signature = EM.attach_fd(@postgres.socket, true)
|
167
|
+
EM.set_notify_readable(@signature, true)
|
168
|
+
EM.instance_variable_get('@conns')[@signature] = self
|
169
|
+
@connected = true
|
170
|
+
next_query
|
171
|
+
|
172
|
+
rescue Exception => e
|
173
|
+
EM.add_timer(1) { reconnect }
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
def execute(sql, cblk = nil, eblk = nil, retries = 0)
|
178
|
+
|
179
|
+
begin
|
180
|
+
if not @processing or not @connected
|
181
|
+
#if !@processing || !@connected
|
182
|
+
@processing = true
|
183
|
+
|
184
|
+
@postgres.send_query(sql)
|
185
|
+
else
|
186
|
+
@queue << [sql, cblk, eblk, retries]
|
187
|
+
return
|
188
|
+
end
|
189
|
+
|
190
|
+
rescue Exception => e
|
191
|
+
puts "error in execute #{e}"
|
192
|
+
if DisconnectErrors.include? e.message
|
193
|
+
@queue << [sql, cblk, eblk, retries]
|
194
|
+
return #close
|
195
|
+
else
|
196
|
+
raise e
|
197
|
+
end
|
198
|
+
end
|
199
|
+
@current = [sql, cblk, eblk, retries]
|
200
|
+
end
|
201
|
+
|
202
|
+
# act like the pg driver
|
203
|
+
def method_missing(method, *args, &blk)
|
204
|
+
@postgres.send(method, *args, &blk) if @postres.respond_to? method
|
205
|
+
end
|
206
|
+
|
207
|
+
def close
|
208
|
+
return unless @connected
|
209
|
+
detach
|
210
|
+
@postgres.finish
|
211
|
+
@connected = false
|
212
|
+
end
|
213
|
+
|
214
|
+
private
|
215
|
+
|
216
|
+
def next_query
|
217
|
+
if @connected and !@processing and pending = @queue.shift
|
218
|
+
sql, cblk, eblk = pending
|
219
|
+
execute(sql, cblk, eblk)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
224
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require "eventmachine"
|
2
|
+
require "pg"
|
3
|
+
require "fcntl"
|
4
|
+
|
5
|
+
=begin
|
6
|
+
module EventMachine
|
7
|
+
class Postgres
|
8
|
+
|
9
|
+
def self.settings
|
10
|
+
@settings ||= { :connections => 1, :logging => false,:database=>"test" }
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.execute query, cblk = nil, eblk = nil, &blk
|
14
|
+
@n ||= 0
|
15
|
+
connection = connection_pool[@n]
|
16
|
+
@n = 0 if (@n+=1) >= connection_pool.size
|
17
|
+
|
18
|
+
#connection.execute(query, type, cblk, eblk, &blk)
|
19
|
+
|
20
|
+
df = EventMachine::DefaultDeferrable.new
|
21
|
+
cb = blk || Proc.new { |r| df.succeed(r) }
|
22
|
+
eb = Proc.new { |r| df.fail(r) }
|
23
|
+
connection.execute(query,cb, eb)
|
24
|
+
df
|
25
|
+
end
|
26
|
+
#class << self
|
27
|
+
# alias query execute
|
28
|
+
#end
|
29
|
+
def self.connection_pool
|
30
|
+
@connection_pool ||= (1..settings[:connections]).map{ EventMachine::PostgresConnection.connect(settings) }
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
=end
|
36
|
+
|
37
|
+
|
38
|
+
module EventMachine
|
39
|
+
class Postgres
|
40
|
+
|
41
|
+
#self::Postgres = ::Postgres unless defined? self::Postgres
|
42
|
+
|
43
|
+
attr_reader :connection
|
44
|
+
|
45
|
+
def initialize(opts)
|
46
|
+
unless EM.respond_to?(:watch) and PGconn.method_defined?(:socket)
|
47
|
+
|
48
|
+
raise RuntimeError, 'pg and EM.watch are required for EventedPostgres'
|
49
|
+
end
|
50
|
+
|
51
|
+
@settings = { :debug => false }.merge!(opts)
|
52
|
+
@connection = connect(@settings)
|
53
|
+
end
|
54
|
+
|
55
|
+
def close
|
56
|
+
@connection.close
|
57
|
+
end
|
58
|
+
|
59
|
+
def query(sql, &blk)
|
60
|
+
df = EventMachine::DefaultDeferrable.new
|
61
|
+
cb = blk || Proc.new { |r| df.succeed(r) }
|
62
|
+
eb = Proc.new { |r| df.fail(r) }
|
63
|
+
|
64
|
+
@connection.execute(sql, cb, eb)
|
65
|
+
|
66
|
+
df
|
67
|
+
end
|
68
|
+
alias :real_query :query
|
69
|
+
alias :execute :query
|
70
|
+
# behave as a normal postgres connection
|
71
|
+
def method_missing(method, *args, &blk)
|
72
|
+
@connection.send(method, *args)
|
73
|
+
end
|
74
|
+
|
75
|
+
def connect(opts)
|
76
|
+
if conn = connect_socket(opts)
|
77
|
+
#debug [:connect, conn.socket, opts]
|
78
|
+
#EM.watch(conn.socket, EventMachine::PostgresConnection, conn, opts, self)
|
79
|
+
|
80
|
+
EM.watch(conn.socket, EventMachine::PostgresConnection,conn,opts,self)
|
81
|
+
else
|
82
|
+
# invokes :errback callback in opts before firing again
|
83
|
+
debug [:reconnect]
|
84
|
+
EM.add_timer(5) { connect opts }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# stolen from sequel
|
89
|
+
def connect_socket(opts)
|
90
|
+
begin
|
91
|
+
conn = PGconn.connect(
|
92
|
+
opts[:host],
|
93
|
+
(opts[:port]), #TODO deal with host and port
|
94
|
+
nil,nil,
|
95
|
+
opts[:database],
|
96
|
+
opts[:user],
|
97
|
+
opts[:password]
|
98
|
+
)
|
99
|
+
# set encoding _before_ connecting
|
100
|
+
if encoding = opts[:encoding] || opts[:charset]
|
101
|
+
if conn.respond_to?(:set_client_encoding)
|
102
|
+
conn.set_client_encoding(encoding)
|
103
|
+
else
|
104
|
+
conn.async_exec("set client_encoding to '#{encoding}'")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
#conn.options(Mysql::OPT_LOCAL_INFILE, 'client')
|
109
|
+
|
110
|
+
# increase timeout so mysql server doesn't disconnect us
|
111
|
+
# this is especially bad if we're disconnected while EM.attach is
|
112
|
+
# still in progress, because by the time it gets to EM, the FD is
|
113
|
+
# no longer valid, and it throws a c++ 'bad file descriptor' error
|
114
|
+
# (do not use a timeout of -1 for unlimited, it does not work on mysqld > 5.0.60)
|
115
|
+
#conn.query("set @@wait_timeout = #{opts[:timeout] || 2592000}")
|
116
|
+
|
117
|
+
# we handle reconnecting (and reattaching the new fd to EM)
|
118
|
+
#conn.reconnect = false
|
119
|
+
|
120
|
+
# By default, MySQL 'where id is null' selects the last inserted id
|
121
|
+
# Turn this off. http://dev.rubyonrails.org/ticket/6778
|
122
|
+
#conn.query("set SQL_AUTO_IS_NULL=0")
|
123
|
+
|
124
|
+
# get results for queries
|
125
|
+
#conn.query_with_result = true
|
126
|
+
|
127
|
+
conn
|
128
|
+
rescue Exception => e
|
129
|
+
puts "#{e} exception"
|
130
|
+
if cb = opts[:errback]
|
131
|
+
cb.call(e)
|
132
|
+
nil
|
133
|
+
else
|
134
|
+
raise e
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def debug(data)
|
140
|
+
p data if @settings[:debug]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
data/spec/helper.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__))
|
2
|
+
require "helper"
|
3
|
+
require "ruby-debug"
|
4
|
+
describe EventMachine::Postgres do
|
5
|
+
|
6
|
+
it "should be true" do
|
7
|
+
true.should be_true
|
8
|
+
end
|
9
|
+
it "should create a new connection" do
|
10
|
+
EventMachine.run {
|
11
|
+
lambda {
|
12
|
+
conn = EventMachine::Postgres.new(:database => "test")
|
13
|
+
EventMachine.stop
|
14
|
+
}.should_not raise_error
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should invoke errback on connection failure" do
|
19
|
+
EventMachine.run {
|
20
|
+
lambda {
|
21
|
+
conn = EventMachine::Postgres.new({
|
22
|
+
:host => 'localhost',
|
23
|
+
:port => 20000,
|
24
|
+
:socket => '',
|
25
|
+
:errback => Proc.new {
|
26
|
+
EventMachine.stop
|
27
|
+
}
|
28
|
+
})
|
29
|
+
}.should_not raise_error
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
it "should execute sql" do
|
35
|
+
EventMachine.run {
|
36
|
+
#EM.add_periodic_timer(1){ puts }
|
37
|
+
conn = EventMachine::Postgres.new(:database => "test")
|
38
|
+
query = conn.execute("select 1;")
|
39
|
+
|
40
|
+
query.callback{ |res|
|
41
|
+
res.first["?column?"].should == "1"
|
42
|
+
EventMachine.stop
|
43
|
+
}
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should accept block as query callback" do
|
48
|
+
EventMachine.run {
|
49
|
+
conn = EventMachine::Postgres.new(:database => 'test')
|
50
|
+
conn.execute("select 1;") { |res|
|
51
|
+
res.first["?column?"].should == "1"
|
52
|
+
EventMachine.stop
|
53
|
+
}
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
it "allow custom error callbacks for each query" do
|
60
|
+
EventMachine.run {
|
61
|
+
conn = EventMachine::Postgres.new(:database => "test")
|
62
|
+
query = conn.execute("select 1 from")
|
63
|
+
query.errback { |res|
|
64
|
+
#res.class.should == Mysql::Error
|
65
|
+
1.should == 1
|
66
|
+
EventMachine.stop
|
67
|
+
1.should == 2 #we should never get here
|
68
|
+
}
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
it "queue up queries and execute them in order" do
|
74
|
+
EventMachine.run {
|
75
|
+
conn = EventMachine::Postgres.new(:database => 'test')
|
76
|
+
|
77
|
+
results = []
|
78
|
+
#debugger
|
79
|
+
conn.execute("select 1 AS x;") {|res| puts res.inspect; results.push(res.first["x"].to_i)}
|
80
|
+
conn.execute("select 2 AS x;") {|res| puts res.inspect;results.push(res.first["x"].to_i)}
|
81
|
+
conn.execute("select 3 AS x;") {|res| puts res.inspect;results.push(res.first["x"].to_i)}
|
82
|
+
#debugger
|
83
|
+
EventMachine.add_timer(0.05) {
|
84
|
+
results.should == [1,2,3]
|
85
|
+
#conn.connection_pool.first.close
|
86
|
+
|
87
|
+
EventMachine.stop
|
88
|
+
}
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
it "queue up large amount of queries and execute them in order" do
|
94
|
+
EventMachine.run {
|
95
|
+
|
96
|
+
conn = EventMachine::Postgres.new(:database => 'test')
|
97
|
+
|
98
|
+
results = []
|
99
|
+
(1..100).each do |i|
|
100
|
+
conn.execute("select #{i} AS x;") {|res| results.push(res.first["x"].to_i)}
|
101
|
+
|
102
|
+
end
|
103
|
+
EventMachine.add_timer(1) {
|
104
|
+
results.should == (1..100).to_a
|
105
|
+
EventMachine.stop
|
106
|
+
}
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
it "should continue processing queries after hitting an error" do
|
112
|
+
EventMachine.run {
|
113
|
+
conn = EventMachine::Postgres.new(:database=> 'test')
|
114
|
+
#errorback = Proc.new{
|
115
|
+
# true.should == true
|
116
|
+
#EventMachine.stop
|
117
|
+
#}
|
118
|
+
q = conn.execute("select 1+ from table;")
|
119
|
+
q.errback{|r| puts "hi"; true.should == true }
|
120
|
+
conn.execute("select 1+1;"){ |res|
|
121
|
+
res.first["?column?"].to_i.should == 2
|
122
|
+
EventMachine.stop
|
123
|
+
}
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
=begin
|
128
|
+
it "should work with synchronous commands" do
|
129
|
+
EventMachine.run {
|
130
|
+
conn = EventMachine::Postgres #.new(:database => 'test')
|
131
|
+
|
132
|
+
conn.list_dbs.class.should == Array
|
133
|
+
conn.list_tables.class.should == Array
|
134
|
+
conn.quote("select '1'").should == "select \\'1\\'"
|
135
|
+
|
136
|
+
EventMachine.stop
|
137
|
+
}
|
138
|
+
end
|
139
|
+
=end
|
140
|
+
# it "should reconnect when disconnected" do
|
141
|
+
# # to test, run:
|
142
|
+
# # mysqladmin5 -u root kill `mysqladmin -u root processlist | grep "select sleep(5)" | cut -d'|' -f2`
|
143
|
+
#
|
144
|
+
# EventMachine.run {
|
145
|
+
# conn = EventMachine::MySQL.new(:host => 'localhost')
|
146
|
+
#
|
147
|
+
# query = conn.query("select sleep(5)")
|
148
|
+
# query.callback {|res|
|
149
|
+
# res.fetch_row.first.to_i.should == 0
|
150
|
+
# EventMachine.stop
|
151
|
+
# }
|
152
|
+
# }
|
153
|
+
# end
|
154
|
+
|
155
|
+
end
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: em-postgres
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Jason Toy
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-08-25 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: eventmachine
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 12
|
31
|
+
- 9
|
32
|
+
version: 0.12.9
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
description: Async PostgreSQL client API for Ruby/EventMachine
|
36
|
+
email: jtoy@jtoy.net
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files: []
|
42
|
+
|
43
|
+
files:
|
44
|
+
- README
|
45
|
+
- Rakefile
|
46
|
+
- em-postgres.gemspec
|
47
|
+
- lib/em-postgres/postgres.rb
|
48
|
+
- lib/em-postgres/connection.rb
|
49
|
+
- lib/em-postgres.rb
|
50
|
+
- spec/helper.rb
|
51
|
+
- spec/postgres_spec.rb
|
52
|
+
has_rdoc: true
|
53
|
+
homepage: http://github.com/jtoy/em-postgres
|
54
|
+
licenses: []
|
55
|
+
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
version: "0"
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
requirements: []
|
78
|
+
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 1.3.7
|
81
|
+
signing_key:
|
82
|
+
specification_version: 3
|
83
|
+
summary: Async PostgreSQL client API for Ruby/EventMachine
|
84
|
+
test_files: []
|
85
|
+
|