async-pool 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +6 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/.travis.yml +20 -0
- data/Gemfile +3 -0
- data/README.md +72 -0
- data/Rakefile +6 -0
- data/async-pool.gemspec +28 -0
- data/lib/async/pool.rb +23 -0
- data/lib/async/pool/controller.rb +208 -0
- data/lib/async/pool/resource.rb +70 -0
- data/lib/async/pool/version.rb +25 -0
- metadata +138 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: df755b3a1ec23182af37b80f498c301e42b0e333c97e663b4f065453c66d36cd
|
4
|
+
data.tar.gz: 1af8d6d7b3f67fcaad73527dbf278133813564ff152c0733cdf4e7da88704334
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 941097d316256c77a43a700468ad8dbd2549a3c433c1a8393913fbeb72d06886b6f0f59d1689902b3ea923e02a2e90ee3dd9269cb14a6b619160aa025d864a80
|
7
|
+
data.tar.gz: a8d87b81f9ec2942d9bb7547b712d239df6fe072f39eb9c6d3d6bc81b16c8a76a79f3ff3fe0746ab7bc8428228fcf391d8a05d7606b13729de878dae80185c96
|
data/.editorconfig
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
language: ruby
|
2
|
+
dist: xenial
|
3
|
+
cache: bundler
|
4
|
+
|
5
|
+
matrix:
|
6
|
+
include:
|
7
|
+
- rvm: 2.3
|
8
|
+
- rvm: 2.4
|
9
|
+
- rvm: 2.5
|
10
|
+
- rvm: 2.6
|
11
|
+
- rvm: 2.6
|
12
|
+
env: COVERAGE=BriefSummary,Coveralls
|
13
|
+
- rvm: ruby-head
|
14
|
+
- rvm: truffleruby
|
15
|
+
- rvm: jruby-head
|
16
|
+
env: JRUBY_OPTS="--debug -X+O"
|
17
|
+
allow_failures:
|
18
|
+
- rvm: ruby-head
|
19
|
+
- rvm: truffleruby
|
20
|
+
- rvm: jruby-head
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Async::Pool
|
2
|
+
|
3
|
+
Provides support for connection pooling both singleplex and multiplex resources.
|
4
|
+
|
5
|
+
[![Build Status](https://travis-ci.com/socketry/async-pool.svg)](https://travis-ci.com/socketry/async-pool)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'async-pool'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install async-pool
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
`Async::Pool::Controller` provides support for both singleplex (one stream at a time) and multiplex resources (multiple streams at a time).
|
26
|
+
|
27
|
+
`Async::Pool::Resource` is provided as an interface and to document how to use the pools. However, you wouldn't need to use this in practice and just implement the appropriate interface on your own objects.
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
pool = Async::Pool::Controller.new(Async::Pool::Resource)
|
31
|
+
|
32
|
+
pool.acquire do |resource|
|
33
|
+
# resource is implicitly released when exiting the block.
|
34
|
+
end
|
35
|
+
|
36
|
+
resource = pool.acquire
|
37
|
+
|
38
|
+
# Return the resource back to the pool:
|
39
|
+
pool.release(resource)
|
40
|
+
```
|
41
|
+
|
42
|
+
## Contributing
|
43
|
+
|
44
|
+
1. Fork it
|
45
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
46
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
47
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
48
|
+
5. Create new Pull Request
|
49
|
+
|
50
|
+
## License
|
51
|
+
|
52
|
+
Released under the MIT license.
|
53
|
+
|
54
|
+
Copyright, 2019, by [Samuel G. D. Williams](http://www.codeotaku.com).
|
55
|
+
|
56
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
57
|
+
of this software and associated documentation files (the "Software"), to deal
|
58
|
+
in the Software without restriction, including without limitation the rights
|
59
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
60
|
+
copies of the Software, and to permit persons to whom the Software is
|
61
|
+
furnished to do so, subject to the following conditions:
|
62
|
+
|
63
|
+
The above copyright notice and this permission notice shall be included in
|
64
|
+
all copies or substantial portions of the Software.
|
65
|
+
|
66
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
67
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
68
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
69
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
70
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
71
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
72
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
data/async-pool.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
require_relative 'lib/async/pool/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = "async-pool"
|
6
|
+
spec.version = Async::Pool::VERSION
|
7
|
+
spec.authors = ["Samuel Williams"]
|
8
|
+
spec.email = ["samuel.williams@oriontransfer.co.nz"]
|
9
|
+
|
10
|
+
spec.summary = "A Redis client library."
|
11
|
+
spec.homepage = "https://github.com/socketry/async-pool"
|
12
|
+
|
13
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
14
|
+
f.match(%r{^(test|spec|features)/})
|
15
|
+
end
|
16
|
+
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency("async", "~> 1.8")
|
21
|
+
|
22
|
+
spec.add_development_dependency "async-rspec", "~> 1.1"
|
23
|
+
|
24
|
+
spec.add_development_dependency "covered"
|
25
|
+
spec.add_development_dependency "bundler"
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.6"
|
27
|
+
spec.add_development_dependency "rake"
|
28
|
+
end
|
data/lib/async/pool.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require_relative 'pool/version'
|
22
|
+
|
23
|
+
require_relative 'pool/controller'
|
@@ -0,0 +1,208 @@
|
|
1
|
+
# Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require 'async/logger'
|
22
|
+
|
23
|
+
require 'async/notification'
|
24
|
+
require 'async/semaphore'
|
25
|
+
|
26
|
+
module Async
|
27
|
+
module Pool
|
28
|
+
class Controller
|
29
|
+
def self.wrap(**options, &block)
|
30
|
+
self.new(block, **options)
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(constructor, limit: nil)
|
34
|
+
@resources = {}
|
35
|
+
@available = Async::Notification.new
|
36
|
+
|
37
|
+
@limit = limit
|
38
|
+
|
39
|
+
@constructor = constructor
|
40
|
+
@guard = Async::Semaphore.new(1)
|
41
|
+
end
|
42
|
+
|
43
|
+
# @attr [Hash<Resource, Integer>] all allocated resources, and their associated usage.
|
44
|
+
attr :resources
|
45
|
+
|
46
|
+
# Whether the pool has any active resources.
|
47
|
+
def active?
|
48
|
+
!@resources.empty?
|
49
|
+
end
|
50
|
+
|
51
|
+
# Whether there are resources which are currently in use.
|
52
|
+
def busy?
|
53
|
+
@resources.collect do |_, usage|
|
54
|
+
return true if usage > 0
|
55
|
+
end
|
56
|
+
|
57
|
+
return false
|
58
|
+
end
|
59
|
+
|
60
|
+
# Wait until a pool resource has been freed.
|
61
|
+
def wait
|
62
|
+
@available.wait
|
63
|
+
end
|
64
|
+
|
65
|
+
def empty?
|
66
|
+
@resources.empty?
|
67
|
+
end
|
68
|
+
|
69
|
+
def acquire
|
70
|
+
resource = wait_for_resource
|
71
|
+
|
72
|
+
return resource unless block_given?
|
73
|
+
|
74
|
+
begin
|
75
|
+
yield resource
|
76
|
+
ensure
|
77
|
+
release(resource)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Make the resource resources and let waiting tasks know that there is something resources.
|
82
|
+
def release(resource)
|
83
|
+
# A resource that is not good should also not be reusable.
|
84
|
+
if resource.reusable?
|
85
|
+
reuse(resource)
|
86
|
+
else
|
87
|
+
retire(resource)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def close
|
92
|
+
@resources.each_key(&:close)
|
93
|
+
@resources.clear
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_s
|
97
|
+
if @resources.empty?
|
98
|
+
"\#<#{self.class}(#{usage_string})>"
|
99
|
+
else
|
100
|
+
"\#<#{self.class}(#{usage_string}) #{availability_string}>"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Retire (and close) all unused resources. If a block is provided, it should implement the desired functionality for unused resources.
|
105
|
+
# @param retain [Integer] the minimum number of resources to retain.
|
106
|
+
# @yield resource [Resource] unused resources.
|
107
|
+
def prune(retain = 0)
|
108
|
+
unused = []
|
109
|
+
|
110
|
+
@resources.each do |resource, usage|
|
111
|
+
unused << resource if usage.zero?
|
112
|
+
end
|
113
|
+
|
114
|
+
unused.each do |resource|
|
115
|
+
if block_given?
|
116
|
+
yield resource
|
117
|
+
else
|
118
|
+
retire(resource)
|
119
|
+
end
|
120
|
+
|
121
|
+
break if @resources.size <= retain
|
122
|
+
end
|
123
|
+
|
124
|
+
return unused.size
|
125
|
+
end
|
126
|
+
|
127
|
+
def retire(resource)
|
128
|
+
Async.logger.debug(self) {"Retire #{resource}"}
|
129
|
+
|
130
|
+
@resources.delete(resource)
|
131
|
+
|
132
|
+
resource.close
|
133
|
+
|
134
|
+
@available.signal
|
135
|
+
end
|
136
|
+
|
137
|
+
protected
|
138
|
+
|
139
|
+
def usage_string
|
140
|
+
"#{@resources.size}/#{@limit || '∞'}"
|
141
|
+
end
|
142
|
+
|
143
|
+
def availability_string
|
144
|
+
@resources.collect do |resource,usage|
|
145
|
+
"#{usage}/#{resource.concurrency}#{resource.viable? ? nil : '*'}/#{resource.count}"
|
146
|
+
end.join(";")
|
147
|
+
end
|
148
|
+
|
149
|
+
def reuse(resource)
|
150
|
+
Async.logger.debug(self) {"Reuse #{resource}"}
|
151
|
+
|
152
|
+
@resources[resource] -= 1
|
153
|
+
|
154
|
+
@available.signal
|
155
|
+
end
|
156
|
+
|
157
|
+
def wait_for_resource
|
158
|
+
# If we fail to create a resource (below), we will end up waiting for one to become resources.
|
159
|
+
until resource = available_resource
|
160
|
+
@available.wait
|
161
|
+
end
|
162
|
+
|
163
|
+
Async.logger.debug(self) {"Wait for resource #{resource}"}
|
164
|
+
|
165
|
+
# if resource.concurrency > 1
|
166
|
+
# @available.signal
|
167
|
+
# end
|
168
|
+
|
169
|
+
return resource
|
170
|
+
end
|
171
|
+
|
172
|
+
def create_resource
|
173
|
+
# This might return nil, which means creating the resource failed.
|
174
|
+
if resource = @constructor.call
|
175
|
+
@resources[resource] = 1
|
176
|
+
end
|
177
|
+
|
178
|
+
return resource
|
179
|
+
end
|
180
|
+
|
181
|
+
def available_resource
|
182
|
+
# TODO This is a linear search... not ideal, but simple for now.
|
183
|
+
@resources.each do |resource, count|
|
184
|
+
if count < resource.concurrency
|
185
|
+
# We want to use this resource... but is it connected?
|
186
|
+
if resource.viable?
|
187
|
+
@resources[resource] += 1
|
188
|
+
|
189
|
+
return resource
|
190
|
+
else
|
191
|
+
retire(resource)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
@guard.acquire do
|
197
|
+
if @limit.nil? or @resources.size < @limit
|
198
|
+
Async.logger.debug(self) {"No resources resources, allocating new one..."}
|
199
|
+
|
200
|
+
return create_resource
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
return nil
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require 'async/logger'
|
22
|
+
|
23
|
+
require 'async/notification'
|
24
|
+
require 'async/semaphore'
|
25
|
+
|
26
|
+
module Async
|
27
|
+
module Pool
|
28
|
+
# The basic interface required by a pool resource.
|
29
|
+
class Resource
|
30
|
+
# Constructs a resource.
|
31
|
+
def self.call
|
32
|
+
self.new
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(concurrency = 1)
|
36
|
+
@concurrency = concurrency
|
37
|
+
@closed = false
|
38
|
+
@count = 0
|
39
|
+
end
|
40
|
+
|
41
|
+
# @attr [Integer] The concurrency of this resource, 1 (singleplex) or more (multiplex).
|
42
|
+
attr :concurrency
|
43
|
+
|
44
|
+
# @attr [Integer] The number of times this resource has been used.
|
45
|
+
attr :count
|
46
|
+
|
47
|
+
# Whether this resource can be acquired.
|
48
|
+
# @return [Boolean] whether the resource can actually be used.
|
49
|
+
def viable?
|
50
|
+
!@closed
|
51
|
+
end
|
52
|
+
|
53
|
+
# Whether the resource has been closed by the user.
|
54
|
+
# @return [Boolean] whether the resource has been closed or has failed.
|
55
|
+
def closed?
|
56
|
+
@closed
|
57
|
+
end
|
58
|
+
|
59
|
+
# Close the resource explicitly, e.g. the pool is being closed.
|
60
|
+
def close
|
61
|
+
@closed = true
|
62
|
+
end
|
63
|
+
|
64
|
+
# Whether this resource can be reused. Used when releasing resources back into the pool.
|
65
|
+
def reusable?
|
66
|
+
!@closed
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
module Async
|
22
|
+
module Pool
|
23
|
+
VERSION = "0.1.0"
|
24
|
+
end
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: async-pool
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Samuel Williams
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-12-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: async
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.8'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: async-rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.1'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: covered
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.6'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.6'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- samuel.williams@oriontransfer.co.nz
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".editorconfig"
|
105
|
+
- ".gitignore"
|
106
|
+
- ".rspec"
|
107
|
+
- ".travis.yml"
|
108
|
+
- Gemfile
|
109
|
+
- README.md
|
110
|
+
- Rakefile
|
111
|
+
- async-pool.gemspec
|
112
|
+
- lib/async/pool.rb
|
113
|
+
- lib/async/pool/controller.rb
|
114
|
+
- lib/async/pool/resource.rb
|
115
|
+
- lib/async/pool/version.rb
|
116
|
+
homepage: https://github.com/socketry/async-pool
|
117
|
+
licenses: []
|
118
|
+
metadata: {}
|
119
|
+
post_install_message:
|
120
|
+
rdoc_options: []
|
121
|
+
require_paths:
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
requirements: []
|
134
|
+
rubygems_version: 3.0.4
|
135
|
+
signing_key:
|
136
|
+
specification_version: 4
|
137
|
+
summary: A Redis client library.
|
138
|
+
test_files: []
|