em-pg-sequel 0.0.3 → 0.0.4
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/Gemfile +2 -2
- data/README.md +2 -1
- data/em-pg-sequel.gemspec +3 -4
- data/lib/em-pg-sequel.rb +2 -45
- data/lib/em-pg-sequel/connection_pool.rb +73 -23
- data/spec/em-pg-sequel/sequel_spec.rb +188 -15
- data/spec/spec_helper.rb +18 -0
- metadata +15 -30
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -8,9 +8,10 @@ Usage
|
|
8
8
|
|
9
9
|
```ruby
|
10
10
|
require "em-pg-sequel"
|
11
|
+
require "em-synchrony"
|
11
12
|
EM.synchrony do
|
12
13
|
url = "postgres://postgres:postgres@localhost:5432/test"
|
13
|
-
db = Sequel.connect(url, pool_class:
|
14
|
+
db = Sequel.connect(url, pool_class: :em_synchrony)
|
14
15
|
|
15
16
|
puts db[:test].all.inspect
|
16
17
|
|
data/em-pg-sequel.gemspec
CHANGED
@@ -4,8 +4,8 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |gem|
|
6
6
|
gem.name = "em-pg-sequel"
|
7
|
-
gem.version = "0.0.
|
8
|
-
gem.authors = ["Petr Yanovich"]
|
7
|
+
gem.version = "0.0.4"
|
8
|
+
gem.authors = ["Petr Yanovich", "Rafal Michalski"]
|
9
9
|
gem.email = ["fl00r@yandex.ru"]
|
10
10
|
gem.description = %q{Sequel adapter for ruby-em-pg-client}
|
11
11
|
gem.summary = %q{Sequel adapter for ruby-em-pg-client}
|
@@ -17,8 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.require_paths = ["lib"]
|
18
18
|
|
19
19
|
gem.add_dependency "sequel"
|
20
|
-
gem.add_dependency "em-
|
21
|
-
gem.add_dependency "em-pg-client"
|
20
|
+
gem.add_dependency "em-pg-client", ">= 0.3.0"
|
22
21
|
|
23
22
|
gem.add_development_dependency "em-synchrony"
|
24
23
|
end
|
data/lib/em-pg-sequel.rb
CHANGED
@@ -1,53 +1,10 @@
|
|
1
|
-
require 'em-
|
2
|
-
require 'em-synchrony/pg'
|
1
|
+
require 'em-pg-client'
|
3
2
|
require 'sequel'
|
4
3
|
require 'em-pg-sequel/connection_pool'
|
5
4
|
|
6
|
-
module EM::PG
|
7
|
-
class ConnectionPool < ::Sequel::ConnectionPool
|
8
|
-
DEFAULT_SIZE = 4
|
9
|
-
attr_accessor :pool
|
10
|
-
def initialize(db, opts = {})
|
11
|
-
super
|
12
|
-
size = opts[:max_connections] || DEFAULT_SIZE
|
13
|
-
@pool = ::EM::PG::Sequel::ConnectionPool.new(size: size, disconnect_class: ::Sequel::DatabaseConnectionError) do
|
14
|
-
make_new(DEFAULT_SERVER)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def size
|
19
|
-
@pool.available.size
|
20
|
-
end
|
21
|
-
|
22
|
-
def hold(server = nil, &blk)
|
23
|
-
@pool.execute(&blk)
|
24
|
-
end
|
25
|
-
|
26
|
-
def disconnect(server = nil)
|
27
|
-
@pool.available.each{ |conn| db.disconnect_connection(conn) }
|
28
|
-
@pool.available.clear
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
module PG::EM
|
34
|
-
class SyncClient < Client
|
35
|
-
# Dirty hack
|
36
|
-
# To avoid patching ruby-em-pg-client and to support Sequel API
|
37
|
-
# we should execute async_client asynchronously for em-pg and synchronously for sequel
|
38
|
-
def async_exec(*args)
|
39
|
-
if block_given?
|
40
|
-
super
|
41
|
-
else
|
42
|
-
exec(*args)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
5
|
$VERBOSE.tap do |old_verbose|
|
49
6
|
$VERBOSE = nil
|
50
|
-
PGconn = PG::EM::
|
7
|
+
PGconn = PG::EM::Client
|
51
8
|
$VERBOSE = old_verbose
|
52
9
|
end
|
53
10
|
|
@@ -1,47 +1,97 @@
|
|
1
1
|
module EM::PG
|
2
2
|
module Sequel
|
3
|
-
class ConnectionPool
|
4
|
-
attr_reader :available
|
3
|
+
class ConnectionPool < ::Sequel::ConnectionPool
|
5
4
|
|
6
|
-
|
5
|
+
DEFAULT_SIZE = 4
|
6
|
+
|
7
|
+
attr_reader :available, :allocated, :max_size
|
8
|
+
|
9
|
+
def initialize(db, opts = {})
|
10
|
+
super
|
7
11
|
@available = []
|
12
|
+
@allocated = {}
|
8
13
|
@pending = []
|
9
|
-
@acquire_blk = blk
|
10
14
|
|
11
|
-
@
|
15
|
+
@max_size = opts[:max_connections] || DEFAULT_SIZE
|
16
|
+
hold {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def size
|
20
|
+
@available.length + @allocated.length
|
21
|
+
end
|
22
|
+
|
23
|
+
def hold(server = nil)
|
24
|
+
fiber = Fiber.current
|
25
|
+
fiber_id = fiber.object_id
|
26
|
+
|
27
|
+
if conn = @allocated[fiber_id]
|
28
|
+
skip_release = true
|
29
|
+
else
|
30
|
+
conn = acquire(fiber) until conn
|
31
|
+
end
|
32
|
+
|
33
|
+
begin
|
34
|
+
yield conn
|
35
|
+
|
36
|
+
rescue ::Sequel::DatabaseDisconnectError => e
|
37
|
+
db.disconnect_connection(conn)
|
38
|
+
drop_failed(fiber_id)
|
39
|
+
skip_release = true
|
12
40
|
|
13
|
-
|
14
|
-
|
41
|
+
raise
|
42
|
+
ensure
|
43
|
+
release(fiber_id) unless skip_release
|
15
44
|
end
|
16
45
|
end
|
17
46
|
|
18
|
-
def
|
19
|
-
conn
|
20
|
-
|
21
|
-
rescue => e
|
22
|
-
conn = @acquire_blk.call if @disconnected_class && @disconnected_class === e
|
23
|
-
raise
|
24
|
-
ensure
|
25
|
-
release(conn)
|
47
|
+
def disconnect(server = nil)
|
48
|
+
@available.each{ |conn| db.disconnect_connection(conn) }
|
49
|
+
@available.clear
|
26
50
|
end
|
27
51
|
|
28
|
-
|
29
|
-
|
52
|
+
private
|
53
|
+
|
54
|
+
def acquire(fiber)
|
30
55
|
if conn = @available.pop
|
31
|
-
conn
|
56
|
+
@allocated[fiber.object_id] = conn
|
32
57
|
else
|
33
|
-
|
34
|
-
|
58
|
+
if size < max_size
|
59
|
+
allocate_new_connection(fiber.object_id)
|
60
|
+
else
|
61
|
+
@pending << fiber
|
62
|
+
Fiber.yield
|
63
|
+
end
|
35
64
|
end
|
36
65
|
end
|
37
66
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
67
|
+
def allocate_new_connection(fiber_id)
|
68
|
+
@allocated[fiber_id] = true
|
69
|
+
@allocated[fiber_id] = make_new(DEFAULT_SERVER)
|
70
|
+
rescue Exception => e
|
71
|
+
drop_failed(fiber_id)
|
72
|
+
raise e
|
73
|
+
end
|
74
|
+
|
75
|
+
# drop failed connection (or a mark) from the pool and
|
76
|
+
# ensure that the pending requests won't starve
|
77
|
+
def drop_failed(fiber_id)
|
78
|
+
@allocated.delete(fiber_id)
|
79
|
+
if pending = @pending.shift
|
80
|
+
EM.next_tick { pending.resume }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def release(fiber_id)
|
85
|
+
conn = @allocated.delete(fiber_id)
|
86
|
+
if pending = @pending.shift
|
87
|
+
@allocated[pending.object_id] = conn
|
88
|
+
EM.next_tick { pending.resume conn}
|
41
89
|
else
|
42
90
|
@available << conn
|
43
91
|
end
|
44
92
|
end
|
93
|
+
|
94
|
+
CONNECTION_POOL_MAP[:em_synchrony] = self
|
45
95
|
end
|
46
96
|
end
|
47
97
|
end
|
@@ -3,20 +3,44 @@ require 'em-synchrony'
|
|
3
3
|
require 'em-synchrony/fiber_iterator'
|
4
4
|
|
5
5
|
describe EM::PG::Sequel do
|
6
|
+
include SynchronyUtils
|
7
|
+
|
6
8
|
DELAY = 1
|
7
9
|
QUERY = "select pg_sleep(#{DELAY})"
|
8
10
|
|
9
11
|
let(:url) { DB_URL }
|
10
12
|
let(:size) { 1 }
|
11
|
-
let(:db) { Sequel.connect(url,
|
13
|
+
let(:db) { Sequel.connect(url, max_connections: size, pool_class: :em_synchrony, db_logger: Logger.new(nil)) }
|
12
14
|
let(:test) { db[:test] }
|
15
|
+
let(:fiber_iterator) { EM::Synchrony::FiberIterator }
|
16
|
+
|
17
|
+
describe "sanity" do
|
18
|
+
let(:size) { 42 }
|
19
|
+
|
20
|
+
it "should have max_size 42" do
|
21
|
+
db.pool.max_size.must_equal 42
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not release nil connection on connect error" do
|
25
|
+
synchrony do
|
26
|
+
db.disconnect
|
27
|
+
db.pool.size.must_equal 0
|
28
|
+
db.pool.stub :allocate_new_connection,
|
29
|
+
proc { raise Sequel::DatabaseConnectionError } do
|
30
|
+
|
31
|
+
proc { test.count }.must_raise Sequel::DatabaseConnectionError
|
32
|
+
db.pool.size.must_equal 0
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
13
38
|
|
14
39
|
describe "unexist table" do
|
15
40
|
it "should raise exception" do
|
16
|
-
|
41
|
+
synchrony do
|
17
42
|
proc { test.all }.must_raise Sequel::DatabaseError
|
18
43
|
|
19
|
-
EM.stop
|
20
44
|
end
|
21
45
|
end
|
22
46
|
end
|
@@ -24,30 +48,27 @@ describe EM::PG::Sequel do
|
|
24
48
|
describe "exist table" do
|
25
49
|
|
26
50
|
before do
|
27
|
-
|
51
|
+
synchrony do
|
28
52
|
db.create_table!(:test) do
|
29
53
|
text :name
|
30
54
|
integer :value, index: true
|
31
55
|
end
|
32
56
|
|
33
|
-
EM.stop
|
34
57
|
end
|
35
58
|
end
|
36
59
|
|
37
60
|
after do
|
38
|
-
|
61
|
+
synchrony do
|
39
62
|
db.drop_table?(:test)
|
40
63
|
|
41
|
-
EM.stop
|
42
64
|
end
|
43
65
|
end
|
44
66
|
|
45
67
|
it "should connect and execute query" do
|
46
|
-
|
68
|
+
synchrony do
|
47
69
|
test.insert name: "andrew", value: 42
|
48
70
|
test.where(name: "andrew").first[:value].must_equal 42
|
49
71
|
|
50
|
-
EM.stop
|
51
72
|
end
|
52
73
|
end
|
53
74
|
|
@@ -55,17 +76,16 @@ describe EM::PG::Sequel do
|
|
55
76
|
describe "pool size is exceeded" do
|
56
77
|
let(:size) { 1 }
|
57
78
|
it "should queue requests" do
|
58
|
-
|
79
|
+
synchrony do
|
59
80
|
start = Time.now.to_f
|
60
81
|
|
61
82
|
res = []
|
62
|
-
|
83
|
+
fiber_iterator.new([1,2], 1).each do |t|
|
63
84
|
res << db[QUERY].all
|
64
85
|
end
|
65
86
|
(Time.now.to_f - start.to_f).must_be_within_delta DELAY * 2, DELAY * 2 * 0.15
|
66
87
|
res.size.must_equal 2
|
67
88
|
|
68
|
-
EM.stop
|
69
89
|
end
|
70
90
|
end
|
71
91
|
end
|
@@ -73,18 +93,171 @@ describe EM::PG::Sequel do
|
|
73
93
|
describe "pool size is enough" do
|
74
94
|
let(:size) { 2 }
|
75
95
|
it "should parallel requests" do
|
76
|
-
|
96
|
+
synchrony do
|
77
97
|
start = Time.now.to_f
|
78
98
|
|
79
99
|
res = []
|
80
|
-
|
100
|
+
fiber_iterator.new([1,2], 2).each do |t|
|
81
101
|
res << db[QUERY].all
|
82
102
|
end
|
83
103
|
|
84
104
|
(Time.now.to_f - start.to_f).must_be_within_delta DELAY, DELAY * 0.30
|
85
105
|
res.size.must_equal 2
|
86
106
|
|
87
|
-
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "pool size is dynamic" do
|
112
|
+
|
113
|
+
let(:size) { 2 }
|
114
|
+
|
115
|
+
it "should have initial size of one" do
|
116
|
+
db.pool.size.must_equal 1
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should allocate second connection" do
|
120
|
+
synchrony do
|
121
|
+
res = []
|
122
|
+
res << test.first
|
123
|
+
db.pool.size.must_equal 1
|
124
|
+
fiber_iterator.new([1,2], 2).each do |t|
|
125
|
+
res << db[QUERY].all
|
126
|
+
end
|
127
|
+
db.pool.size.must_equal 2
|
128
|
+
res.size.must_equal 3
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should not create more than size connections" do
|
134
|
+
synchrony do
|
135
|
+
db.pool.size.must_equal 1
|
136
|
+
|
137
|
+
start = Time.now.to_f
|
138
|
+
res = []
|
139
|
+
fiber_iterator.new([1,1,2], 3).each do |pool_size|
|
140
|
+
db.pool.size.must_equal pool_size
|
141
|
+
res << db[QUERY].all
|
142
|
+
end
|
143
|
+
|
144
|
+
(Time.now.to_f - start.to_f).must_be_within_delta DELAY*2, DELAY * 2.60
|
145
|
+
res.size.must_equal 3
|
146
|
+
|
147
|
+
db.pool.size.must_equal size
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should clear all connections on disconnect" do
|
153
|
+
synchrony do
|
154
|
+
db.disconnect
|
155
|
+
db.pool.size.must_equal 0
|
156
|
+
res = []
|
157
|
+
fiber_iterator.new([1,2,3], 3).each do |t|
|
158
|
+
res << test.count
|
159
|
+
end
|
160
|
+
res.size.must_equal 3
|
161
|
+
db.pool.size.must_equal size
|
162
|
+
db.disconnect
|
163
|
+
db.pool.size.must_equal 0
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should re-create 1st connection" do
|
169
|
+
synchrony do
|
170
|
+
db.disconnect
|
171
|
+
db.pool.size.must_equal 0
|
172
|
+
|
173
|
+
test.count.must_equal 0
|
174
|
+
db.pool.size.must_equal 1
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "on connection errors" do
|
182
|
+
|
183
|
+
let(:size) { 3 }
|
184
|
+
|
185
|
+
it "should not leave pending requests in queue" do
|
186
|
+
synchrony do
|
187
|
+
db.disconnect
|
188
|
+
fiber_iterator.new((0..size), size).each { test.count }
|
189
|
+
db.pool.available.each do |conn|
|
190
|
+
# force clients to disconnected state
|
191
|
+
conn.async_command_aborted = true
|
192
|
+
end.length.must_equal db.pool.size
|
193
|
+
|
194
|
+
db.pool.stub :make_new,
|
195
|
+
proc {
|
196
|
+
EM::Synchrony.sleep 0.1
|
197
|
+
raise Sequel::DatabaseConnectionError } do
|
198
|
+
|
199
|
+
request_counter = 0
|
200
|
+
expected_runs = db.pool.max_size + 10
|
201
|
+
expected_runs.times do |index|
|
202
|
+
Fiber.new do
|
203
|
+
|
204
|
+
pending = db.pool.instance_eval { @pending.length }
|
205
|
+
pending.must_equal [index - db.pool.max_size, 0].max
|
206
|
+
|
207
|
+
if index < db.pool.max_size
|
208
|
+
proc { test.count }.must_raise Sequel::DatabaseDisconnectError
|
209
|
+
else
|
210
|
+
proc { test.count }.must_raise Sequel::DatabaseConnectionError
|
211
|
+
end
|
212
|
+
|
213
|
+
request_counter += 1
|
214
|
+
|
215
|
+
end.resume
|
216
|
+
end
|
217
|
+
|
218
|
+
db.pool.instance_eval { @pending.length }.must_equal 10
|
219
|
+
|
220
|
+
tick_sleep while request_counter < expected_runs
|
221
|
+
|
222
|
+
db.pool.instance_eval { @pending.length }.must_equal 0
|
223
|
+
db.pool.size.must_equal 0
|
224
|
+
request_counter.must_equal expected_runs
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
describe "play nice with transactions" do
|
232
|
+
|
233
|
+
let(:size) { 2 }
|
234
|
+
|
235
|
+
it "should lock connection to fiber" do
|
236
|
+
synchrony do
|
237
|
+
db.transaction do |conn|
|
238
|
+
db.in_transaction?.must_equal true
|
239
|
+
db.transaction do |inner_conn|
|
240
|
+
inner_conn.must_be_same_as conn
|
241
|
+
db.in_transaction?.must_equal true
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should allow separate transactions" do
|
249
|
+
synchrony do
|
250
|
+
db.transaction do |conn|
|
251
|
+
db.in_transaction?.must_equal true
|
252
|
+
fiber_iterator.new([1,2], 2).each do |t|
|
253
|
+
db.in_transaction?.must_equal false
|
254
|
+
db.transaction do |inner_conn|
|
255
|
+
inner_conn.wont_be_same_as conn
|
256
|
+
db.in_transaction?.must_equal true
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
88
261
|
end
|
89
262
|
end
|
90
263
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -16,6 +16,24 @@ DB_CONFIG = {
|
|
16
16
|
password: "postgres",
|
17
17
|
}
|
18
18
|
|
19
|
+
module SynchronyUtils
|
20
|
+
def tick_sleep
|
21
|
+
f = Fiber.current
|
22
|
+
EM::next_tick { f.resume }
|
23
|
+
Fiber.yield
|
24
|
+
end
|
25
|
+
|
26
|
+
def synchrony
|
27
|
+
EM.synchrony do
|
28
|
+
begin
|
29
|
+
yield
|
30
|
+
ensure
|
31
|
+
EM.stop
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
19
37
|
DB_URL = "postgres://%s:%s@%s:%d/%s" % [DB_CONFIG[:user], DB_CONFIG[:password], DB_CONFIG[:host], DB_CONFIG[:port], DB_CONFIG[:dbname]]
|
20
38
|
|
21
39
|
MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
|
metadata
CHANGED
@@ -1,80 +1,65 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-pg-sequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Petr Yanovich
|
9
|
+
- Rafal Michalski
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
13
|
+
date: 2014-01-03 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: sequel
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ! '>='
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '0'
|
22
|
-
type: :runtime
|
23
17
|
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ! '>='
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '0'
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: em-synchrony
|
32
18
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
19
|
requirements:
|
35
20
|
- - ! '>='
|
36
21
|
- !ruby/object:Gem::Version
|
37
22
|
version: '0'
|
23
|
+
none: false
|
38
24
|
type: :runtime
|
39
|
-
prerelease: false
|
40
25
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
26
|
requirements:
|
43
27
|
- - ! '>='
|
44
28
|
- !ruby/object:Gem::Version
|
45
29
|
version: '0'
|
30
|
+
none: false
|
46
31
|
- !ruby/object:Gem::Dependency
|
47
32
|
name: em-pg-client
|
33
|
+
prerelease: false
|
48
34
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
35
|
requirements:
|
51
36
|
- - ! '>='
|
52
37
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
38
|
+
version: 0.3.0
|
39
|
+
none: false
|
54
40
|
type: :runtime
|
55
|
-
prerelease: false
|
56
41
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
42
|
requirements:
|
59
43
|
- - ! '>='
|
60
44
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
45
|
+
version: 0.3.0
|
46
|
+
none: false
|
62
47
|
- !ruby/object:Gem::Dependency
|
63
48
|
name: em-synchrony
|
49
|
+
prerelease: false
|
64
50
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
51
|
requirements:
|
67
52
|
- - ! '>='
|
68
53
|
- !ruby/object:Gem::Version
|
69
54
|
version: '0'
|
55
|
+
none: false
|
70
56
|
type: :development
|
71
|
-
prerelease: false
|
72
57
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
58
|
requirements:
|
75
59
|
- - ! '>='
|
76
60
|
- !ruby/object:Gem::Version
|
77
61
|
version: '0'
|
62
|
+
none: false
|
78
63
|
description: Sequel adapter for ruby-em-pg-client
|
79
64
|
email:
|
80
65
|
- fl00r@yandex.ru
|
@@ -99,17 +84,17 @@ rdoc_options: []
|
|
99
84
|
require_paths:
|
100
85
|
- lib
|
101
86
|
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
-
none: false
|
103
87
|
requirements:
|
104
88
|
- - ! '>='
|
105
89
|
- !ruby/object:Gem::Version
|
106
90
|
version: '0'
|
107
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
91
|
none: false
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
93
|
requirements:
|
110
94
|
- - ! '>='
|
111
95
|
- !ruby/object:Gem::Version
|
112
96
|
version: '0'
|
97
|
+
none: false
|
113
98
|
requirements: []
|
114
99
|
rubyforge_project:
|
115
100
|
rubygems_version: 1.8.24
|