em-pg 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +10 -0
- data/Gemfile.lock +44 -0
- data/README.md +91 -0
- data/Rakefile +121 -0
- data/em-pg.gemspec +26 -0
- data/lib/em/pg.rb +220 -0
- data/spec/em/pg_spec.rb +83 -0
- data/spec/spec_helper.rb +23 -0
- metadata +84 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
em-pg (0.1.0)
|
5
|
+
eventmachine (>= 0.12)
|
6
|
+
pg (>= 0.14)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
ansi (1.4.3)
|
12
|
+
builder (3.1.4)
|
13
|
+
columnize (0.3.6)
|
14
|
+
debugger (1.2.2)
|
15
|
+
columnize (>= 0.3.1)
|
16
|
+
debugger-linecache (~> 1.1.1)
|
17
|
+
debugger-ruby_core_source (~> 1.1.5)
|
18
|
+
debugger-linecache (1.1.2)
|
19
|
+
debugger-ruby_core_source (>= 1.1.1)
|
20
|
+
debugger-ruby_core_source (1.1.5)
|
21
|
+
eventmachine (1.0.0)
|
22
|
+
hashie (1.2.0)
|
23
|
+
minitest (4.1.0)
|
24
|
+
minitest-em-sync (0.1.0)
|
25
|
+
eventmachine (>= 0.12)
|
26
|
+
minitest-reporters (0.12.0)
|
27
|
+
ansi
|
28
|
+
builder
|
29
|
+
minitest (>= 2.12, < 5.0)
|
30
|
+
powerbar
|
31
|
+
pg (0.14.1)
|
32
|
+
powerbar (1.0.11)
|
33
|
+
ansi (~> 1.4.0)
|
34
|
+
hashie (>= 1.1.0)
|
35
|
+
|
36
|
+
PLATFORMS
|
37
|
+
ruby
|
38
|
+
|
39
|
+
DEPENDENCIES
|
40
|
+
debugger
|
41
|
+
em-pg!
|
42
|
+
minitest
|
43
|
+
minitest-em-sync
|
44
|
+
minitest-reporters
|
data/README.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
EM::PG
|
2
|
+
======
|
3
|
+
|
4
|
+
One more EventMachine wrapper for Postgresql [pg-lib](https://github.com/ged/ruby-pg).
|
5
|
+
|
6
|
+
Features
|
7
|
+
--------
|
8
|
+
|
9
|
+
* Fully async including connect and right usage of #busy and #consume_input;
|
10
|
+
* All results are standard deferrable objects;
|
11
|
+
* Distinct exceptions hierarchy;
|
12
|
+
* Wrapper for [Green](https://github.com/prepor/green) and adapter fot [Sequel](http://sequel.rubyforge.org/).
|
13
|
+
|
14
|
+
Usage
|
15
|
+
-----
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem "em-pg"
|
19
|
+
```
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
require "em/pg"
|
23
|
+
|
24
|
+
EM.run do
|
25
|
+
db = EM::PG.new host: "localhost", port: 5432, dbname: "test", user: "postgres", password: "postgres"
|
26
|
+
db.callback do
|
27
|
+
q = db.send_query "select 1"
|
28
|
+
q.callback do |res|
|
29
|
+
puts "RESULT: #{res.inspect}"
|
30
|
+
EM.stop
|
31
|
+
end
|
32
|
+
q.errback do |e|
|
33
|
+
raise e
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
db.errback do |e|
|
38
|
+
raise e
|
39
|
+
end
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
To all errbacks pass one argument, instance of EM::PG::Error. So it easy to write common handlers and wrappers for something like EM-Synchrony and Green.
|
44
|
+
|
45
|
+
### Supported methods
|
46
|
+
|
47
|
+
* `send_query`
|
48
|
+
* `send_prepare`
|
49
|
+
* `send_query_prepared`
|
50
|
+
* `send_describe_prepared`
|
51
|
+
* `send_describe_portal`
|
52
|
+
|
53
|
+
All have same semantics as in pg-lib, but result is a Deferrable object
|
54
|
+
|
55
|
+
### Disconnects
|
56
|
+
|
57
|
+
On disconnect all current queries will be failed with exception DisconnectError. You also can pass :on_disconnect callback with options, wich will be called before queries errbacks.
|
58
|
+
|
59
|
+
EM::PG doesn't have reconnect strategy, you should handle disconnects by youself.
|
60
|
+
|
61
|
+
### Logging
|
62
|
+
|
63
|
+
You can pass :logger option or set `EM::PG.logger` for all instances.
|
64
|
+
|
65
|
+
Exceptions
|
66
|
+
----------
|
67
|
+
|
68
|
+
```
|
69
|
+
EM::PG::Error
|
70
|
+
ConnectionRefusedError
|
71
|
+
DisconnectError
|
72
|
+
BadStateError
|
73
|
+
UnexpectedStateError
|
74
|
+
BadConnectionStatusError
|
75
|
+
BadPollStatusError
|
76
|
+
PGError
|
77
|
+
```
|
78
|
+
|
79
|
+
* ConnectionRefusedError - can't connect. Have field `.message` with reason;
|
80
|
+
* DisconnectError - connection disconnected. Will be raised on all uncompleted queries;
|
81
|
+
* BadStateError - you try do something while a wrong state. For example send query on not connected client;
|
82
|
+
* UnexpectedStateError - something gone wrong :(
|
83
|
+
* PGError - original PG exceptions was raised. Have field `.original`.
|
84
|
+
|
85
|
+
See also
|
86
|
+
--------
|
87
|
+
|
88
|
+
* [em-pg-client](https://github.com/royaltm/ruby-em-pg-client) - good wrapper around pg-lib with reconnects.
|
89
|
+
* [em-postgres](https://github.com/jtoy/em-postgres)
|
90
|
+
* [em-postgresql-sequel](https://github.com/jzimmek/em-postgresql-sequel)
|
91
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
#############################################################################
|
6
|
+
#
|
7
|
+
# Helper functions
|
8
|
+
#
|
9
|
+
#############################################################################
|
10
|
+
|
11
|
+
def name
|
12
|
+
@name ||= Dir['*.gemspec'].first.split('.').first
|
13
|
+
end
|
14
|
+
|
15
|
+
def version
|
16
|
+
line = File.read("lib/em/pg.rb")[/^\s*VERSION\s*=\s*.*/]
|
17
|
+
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
|
18
|
+
end
|
19
|
+
|
20
|
+
def date
|
21
|
+
Date.today.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def rubyforge_project
|
25
|
+
name
|
26
|
+
end
|
27
|
+
|
28
|
+
def gemspec_file
|
29
|
+
"#{name}.gemspec"
|
30
|
+
end
|
31
|
+
|
32
|
+
def gem_file
|
33
|
+
"#{name}-#{version}.gem"
|
34
|
+
end
|
35
|
+
|
36
|
+
def replace_header(head, header_name)
|
37
|
+
head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
|
38
|
+
end
|
39
|
+
|
40
|
+
#############################################################################
|
41
|
+
#
|
42
|
+
# Standard tasks
|
43
|
+
#
|
44
|
+
#############################################################################
|
45
|
+
|
46
|
+
task :default => :spec
|
47
|
+
|
48
|
+
require 'rake/testtask'
|
49
|
+
Rake::TestTask.new(:spec) do |test|
|
50
|
+
test.libs << 'lib' << 'spec'
|
51
|
+
test.pattern = 'spec/**/*_spec.rb'
|
52
|
+
test.verbose = true
|
53
|
+
end
|
54
|
+
|
55
|
+
desc "Open an irb session preloaded with this library"
|
56
|
+
task :console do
|
57
|
+
sh "irb -rubygems -r ./lib/#{name}.rb"
|
58
|
+
end
|
59
|
+
|
60
|
+
#############################################################################
|
61
|
+
#
|
62
|
+
# Custom tasks (add your own tasks here)
|
63
|
+
#
|
64
|
+
#############################################################################
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
#############################################################################
|
69
|
+
#
|
70
|
+
# Packaging tasks
|
71
|
+
#
|
72
|
+
#############################################################################
|
73
|
+
|
74
|
+
desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
|
75
|
+
task :release => :build do
|
76
|
+
unless `git branch` =~ /^\* master$/
|
77
|
+
puts "You must be on the master branch to release!"
|
78
|
+
exit!
|
79
|
+
end
|
80
|
+
sh "git commit --allow-empty -a -m 'Release #{version}'"
|
81
|
+
sh "git tag v#{version}"
|
82
|
+
sh "git push origin master"
|
83
|
+
sh "git push origin v#{version}"
|
84
|
+
sh "gem push pkg/#{name}-#{version}.gem"
|
85
|
+
end
|
86
|
+
|
87
|
+
desc "Build #{gem_file} into the pkg directory"
|
88
|
+
task :build => :gemspec do
|
89
|
+
sh "mkdir -p pkg"
|
90
|
+
sh "gem build #{gemspec_file}"
|
91
|
+
sh "mv #{gem_file} pkg"
|
92
|
+
end
|
93
|
+
|
94
|
+
desc "Generate #{gemspec_file}"
|
95
|
+
task :gemspec do
|
96
|
+
# read spec file and split out manifest section
|
97
|
+
spec = File.read(gemspec_file)
|
98
|
+
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
99
|
+
|
100
|
+
# replace name version and date
|
101
|
+
replace_header(head, :name)
|
102
|
+
replace_header(head, :version)
|
103
|
+
replace_header(head, :date)
|
104
|
+
#comment this out if your rubyforge_project has a different name
|
105
|
+
replace_header(head, :rubyforge_project)
|
106
|
+
|
107
|
+
# determine file list from git ls-files
|
108
|
+
files = `git ls-files`.
|
109
|
+
split("\n").
|
110
|
+
sort.
|
111
|
+
reject { |file| file =~ /^\./ }.
|
112
|
+
reject { |file| file =~ /^(rdoc|pkg)/ }.
|
113
|
+
map { |file| " #{file}" }.
|
114
|
+
join("\n")
|
115
|
+
|
116
|
+
# piece file back together and write
|
117
|
+
manifest = " s.files = %w[\n#{files}\n ]\n"
|
118
|
+
spec = [head, manifest, tail].join(" # = MANIFEST =\n")
|
119
|
+
File.open(gemspec_file, 'w') { |io| io.write(spec) }
|
120
|
+
puts "Updated #{gemspec_file}"
|
121
|
+
end
|
data/em-pg.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
spec = Gem::Specification.new do |s|
|
2
|
+
s.name = 'em-pg'
|
3
|
+
s.version = '0.1.0'
|
4
|
+
s.date = '2013-01-28'
|
5
|
+
s.summary = 'Async PostgreSQL client API for Ruby/EventMachine'
|
6
|
+
s.email = "ceo@prepor.ru"
|
7
|
+
s.homepage = "http://github.com/prepor/em-postgres"
|
8
|
+
s.description = 'Async PostgreSQL client API for Ruby/EventMachine'
|
9
|
+
s.has_rdoc = false
|
10
|
+
s.authors = ["Andrew Rudenko"]
|
11
|
+
s.add_dependency('eventmachine', '>= 0.12')
|
12
|
+
s.add_dependency('pg', '>= 0.14')
|
13
|
+
|
14
|
+
# = MANIFEST =
|
15
|
+
s.files = %w[
|
16
|
+
Gemfile
|
17
|
+
Gemfile.lock
|
18
|
+
README.md
|
19
|
+
Rakefile
|
20
|
+
em-pg.gemspec
|
21
|
+
lib/em/pg.rb
|
22
|
+
spec/em/pg_spec.rb
|
23
|
+
spec/spec_helper.rb
|
24
|
+
]
|
25
|
+
# = MANIFEST =
|
26
|
+
end
|
data/lib/em/pg.rb
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'pg'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module EM
|
6
|
+
class PG
|
7
|
+
VERSION = '0.1.0'
|
8
|
+
include EM::Deferrable
|
9
|
+
|
10
|
+
class Error < RuntimeError
|
11
|
+
def initialize(params = {})
|
12
|
+
params.each { |k, v| self.send("#{k}=", v) }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
class ConnectionRefusedError < Error
|
16
|
+
attr_accessor :message
|
17
|
+
end
|
18
|
+
class DisconnectError < Error; end
|
19
|
+
class BadStateError < Error
|
20
|
+
attr_accessor :state
|
21
|
+
end
|
22
|
+
class UnexpectedStateError < Error; end
|
23
|
+
class BadConnectionStatusError < UnexpectedStateError; end
|
24
|
+
class BadPollStatusError < UnexpectedStateError; end
|
25
|
+
class PGError < Error
|
26
|
+
attr_accessor :original
|
27
|
+
end
|
28
|
+
|
29
|
+
class Watcher < EM::Connection
|
30
|
+
attr_accessor :postgres
|
31
|
+
def initialize(postgres)
|
32
|
+
@postgres = postgres
|
33
|
+
end
|
34
|
+
|
35
|
+
def notify_readable
|
36
|
+
@postgres.handle
|
37
|
+
end
|
38
|
+
|
39
|
+
def notify_writable
|
40
|
+
self.notify_writable = false
|
41
|
+
@postgres.handle
|
42
|
+
end
|
43
|
+
|
44
|
+
def unbind
|
45
|
+
@postgres.unbind
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
class Query
|
52
|
+
include EM::Deferrable
|
53
|
+
attr_accessor :method, :args
|
54
|
+
def initialize(method, args)
|
55
|
+
@method, @args = method, args
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class << self
|
60
|
+
attr_accessor :logger
|
61
|
+
end
|
62
|
+
self.logger = Logger.new(STDOUT)
|
63
|
+
|
64
|
+
attr_accessor :pg, :conn, :opts, :state, :logger, :watcher, :on_disconnect
|
65
|
+
def initialize(opts)
|
66
|
+
opts = opts.dup
|
67
|
+
@logger = opts.delete(:logger) || EM::Postgres.logger
|
68
|
+
@on_disconnect = opts.delete(:on_disconnect)
|
69
|
+
@opts = opts
|
70
|
+
@state = :connecting
|
71
|
+
|
72
|
+
@pg = ::PG::Connection.connect_start(@opts)
|
73
|
+
@queue = []
|
74
|
+
|
75
|
+
@watcher = EM.watch(@pg.socket, Watcher, self)
|
76
|
+
@watcher.notify_readable = true
|
77
|
+
check_connect
|
78
|
+
end
|
79
|
+
|
80
|
+
def handle
|
81
|
+
case @state
|
82
|
+
when :connecting
|
83
|
+
check_connect
|
84
|
+
when :waiting
|
85
|
+
consume_result do |res|
|
86
|
+
result_for_query res
|
87
|
+
end
|
88
|
+
else # try check result, may be it close-message
|
89
|
+
consume_result do |res|
|
90
|
+
if res.is_a? Exception
|
91
|
+
unbind res
|
92
|
+
else
|
93
|
+
error "Result in unexpected state #{@state}: #{res.inspect}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def check_connect
|
100
|
+
status = @pg.connect_poll
|
101
|
+
case status
|
102
|
+
when ::PG::PGRES_POLLING_OK
|
103
|
+
if pg.status == ::PG::CONNECTION_OK
|
104
|
+
connected
|
105
|
+
elsif pg.status == ::PG::CONNECTION_BAD
|
106
|
+
connection_refused
|
107
|
+
else
|
108
|
+
raise BadConnectionStatusError.new
|
109
|
+
end
|
110
|
+
when ::PG::PGRES_POLLING_READING
|
111
|
+
when ::PG::PGRES_POLLING_WRITING
|
112
|
+
@watcher.notify_writable = true
|
113
|
+
when ::PG::PGRES_POLLING_FAILED
|
114
|
+
@watcher.detach
|
115
|
+
connection_refused
|
116
|
+
else
|
117
|
+
raise BadPollStatsError.new
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
[:send_query, :send_prepare, :send_query_prepared, :send_describe_prepared, :send_describe_portal].each do |m|
|
122
|
+
define_method(m) do |*args|
|
123
|
+
make_query(m, *args)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def make_query(m, *args)
|
128
|
+
q = Query.new m, args
|
129
|
+
case @state
|
130
|
+
when :waiting
|
131
|
+
add_to_queue q
|
132
|
+
when :connected
|
133
|
+
run_query! q
|
134
|
+
else
|
135
|
+
q.fail BadStateError.new(state: @state)
|
136
|
+
end
|
137
|
+
q
|
138
|
+
end
|
139
|
+
|
140
|
+
def add_to_queue(query)
|
141
|
+
@queue << query
|
142
|
+
end
|
143
|
+
|
144
|
+
def run_query!(q)
|
145
|
+
@current_query = q
|
146
|
+
@state = :waiting
|
147
|
+
debug(["EM::PG", q.method, q.args])
|
148
|
+
@pg.send(q.method, *q.args)
|
149
|
+
end
|
150
|
+
|
151
|
+
def try_next_from_queue
|
152
|
+
q = @queue.shift
|
153
|
+
if q
|
154
|
+
run_query! q
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def consume_result(&clb)
|
159
|
+
begin
|
160
|
+
@pg.consume_input # can raise exceptins
|
161
|
+
if @pg.is_busy
|
162
|
+
else
|
163
|
+
clb.call @pg.get_last_result # can raise exceptions
|
164
|
+
end
|
165
|
+
rescue ::PG::Error => e
|
166
|
+
clb.call PGError.new(original: e)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def result_for_query(res)
|
171
|
+
@state = :connected
|
172
|
+
q = @current_query
|
173
|
+
@current_query = nil
|
174
|
+
if res.is_a? Exception
|
175
|
+
q.fail res
|
176
|
+
else
|
177
|
+
q.succeed res
|
178
|
+
end
|
179
|
+
try_next_from_queue
|
180
|
+
end
|
181
|
+
|
182
|
+
def connected
|
183
|
+
@state = :connected
|
184
|
+
succeed :connected
|
185
|
+
end
|
186
|
+
|
187
|
+
def connection_refused
|
188
|
+
@state = :connection_refused
|
189
|
+
logger.error [:connection_refused, @pg.error_message]
|
190
|
+
fail ConnectionRefusedError.new(message: @pg.error_message)
|
191
|
+
end
|
192
|
+
|
193
|
+
def unbind(reason = nil)
|
194
|
+
return if @state == :disconnected
|
195
|
+
logger.error [:disconnected, reason]
|
196
|
+
@state = :disconnected
|
197
|
+
@watcher.detach
|
198
|
+
@on_disconnect.call if @on_disconnect
|
199
|
+
fail_queries DisconnectError.new
|
200
|
+
end
|
201
|
+
|
202
|
+
def close
|
203
|
+
@state = :closed
|
204
|
+
@watcher.detach
|
205
|
+
@pg.finish
|
206
|
+
fail_queries :closed
|
207
|
+
end
|
208
|
+
|
209
|
+
def fail_queries(exc)
|
210
|
+
@current_query.fail exc if @current_query
|
211
|
+
@queue.each { |q| q.fail exc }
|
212
|
+
end
|
213
|
+
|
214
|
+
[:trace, :debug, :info, :warn, :error, :fatal].each do |m|
|
215
|
+
define_method(m) do |*args, &blk|
|
216
|
+
logger.send(m, *args, &blk)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
data/spec/em/pg_spec.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
describe EM::PG do
|
3
|
+
let(:db_options) do
|
4
|
+
{}
|
5
|
+
end
|
6
|
+
let(:db) do
|
7
|
+
EM::PG.new(DB_CONFIG.merge(db_options)).tap { |o| sync o }
|
8
|
+
end
|
9
|
+
|
10
|
+
include Minitest::EMSync
|
11
|
+
|
12
|
+
it "should invoke errback on connection failure" do
|
13
|
+
conn = EM::PG.new(DB_CONFIG.merge user: "unexist")
|
14
|
+
proc { sync conn }.must_raise EM::PG::ConnectionRefusedError
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "with on_disconnect" do
|
18
|
+
let(:m) { EM::DefaultDeferrable.new }
|
19
|
+
|
20
|
+
let(:db_options) do
|
21
|
+
{ on_disconnect: proc { m.succeed } }
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should invoke on_disconnect" do
|
25
|
+
db
|
26
|
+
EM.next_tick { db.unbind } # don't known how to emulate real disconnect
|
27
|
+
sync m
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should fail current queries on disconnect" do
|
32
|
+
q1 = db.send_query("select pg_sleep(10);")
|
33
|
+
q2 = db.send_query("select pg_sleep(10);")
|
34
|
+
EM.next_tick { db.unbind }
|
35
|
+
proc { sync q1 }.must_raise EM::PG::DisconnectError
|
36
|
+
proc { sync q2 }.must_raise EM::PG::DisconnectError
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "successful connection" do
|
40
|
+
after do
|
41
|
+
db.close
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should create a new connection" do
|
45
|
+
db.state.must_equal :connected
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should execute sql" do
|
49
|
+
query = db.send_query("select 1;")
|
50
|
+
res = sync query
|
51
|
+
res.first["?column?"].must_equal "1"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "allow custom error callbacks for each query" do
|
55
|
+
query = db.send_query("select 1 from")
|
56
|
+
proc { sync query }.must_raise EM::PG::PGError
|
57
|
+
end
|
58
|
+
|
59
|
+
it "queue up large amount of queries and execute them in order" do
|
60
|
+
results = []
|
61
|
+
m = EM::DefaultDeferrable.new
|
62
|
+
100.times do |i|
|
63
|
+
db.send_query("select #{i} AS x;").callback do |res|
|
64
|
+
results << res.first["x"].to_i
|
65
|
+
if results.size == 100
|
66
|
+
results.reduce(0, &:+).must_equal 100.times.reduce(0, &:+)
|
67
|
+
m.succeed
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
sync m
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "not yet connected" do
|
75
|
+
let(:db) { EM::PG.new DB_CONFIG }
|
76
|
+
it "should fail query" do
|
77
|
+
q1 = db.send_query("select 1;")
|
78
|
+
proc { sync q1 }.must_raise EM::PG::BadStateError
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
|
5
|
+
require 'em/pg'
|
6
|
+
|
7
|
+
require 'minitest/spec'
|
8
|
+
require 'minitest/autorun'
|
9
|
+
require 'minitest/reporters'
|
10
|
+
require 'minitest/em_sync'
|
11
|
+
|
12
|
+
logger = Logger.new nil
|
13
|
+
|
14
|
+
DB_CONFIG = {
|
15
|
+
host: "localhost",
|
16
|
+
port: 5432,
|
17
|
+
dbname: "test",
|
18
|
+
user: "postgres",
|
19
|
+
password: "postgres",
|
20
|
+
logger: logger
|
21
|
+
}
|
22
|
+
|
23
|
+
MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: em-pg
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Andrew Rudenko
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: eventmachine
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.12'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.12'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: pg
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0.14'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0.14'
|
46
|
+
description: Async PostgreSQL client API for Ruby/EventMachine
|
47
|
+
email: ceo@prepor.ru
|
48
|
+
executables: []
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- Gemfile
|
53
|
+
- Gemfile.lock
|
54
|
+
- README.md
|
55
|
+
- Rakefile
|
56
|
+
- em-pg.gemspec
|
57
|
+
- lib/em/pg.rb
|
58
|
+
- spec/em/pg_spec.rb
|
59
|
+
- spec/spec_helper.rb
|
60
|
+
homepage: http://github.com/prepor/em-postgres
|
61
|
+
licenses: []
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 1.8.24
|
81
|
+
signing_key:
|
82
|
+
specification_version: 3
|
83
|
+
summary: Async PostgreSQL client API for Ruby/EventMachine
|
84
|
+
test_files: []
|