async-pool 0.1.0 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df755b3a1ec23182af37b80f498c301e42b0e333c97e663b4f065453c66d36cd
4
- data.tar.gz: 1af8d6d7b3f67fcaad73527dbf278133813564ff152c0733cdf4e7da88704334
3
+ metadata.gz: 91d47d29e5bb2e6a93668145c06b432ee26393019cb253d284ffb48cf2c8285b
4
+ data.tar.gz: 3b3d98e86aec3e783fa5ed98eb803d0f8efe382c0f4b32d518779c09ca736c2d
5
5
  SHA512:
6
- metadata.gz: 941097d316256c77a43a700468ad8dbd2549a3c433c1a8393913fbeb72d06886b6f0f59d1689902b3ea923e02a2e90ee3dd9269cb14a6b619160aa025d864a80
7
- data.tar.gz: a8d87b81f9ec2942d9bb7547b712d239df6fe072f39eb9c6d3d6bc81b16c8a76a79f3ff3fe0746ab7bc8428228fcf391d8a05d7606b13729de878dae80185c96
6
+ metadata.gz: 34260d06050fe9829ddd40c2a29444548707661262e34df4bd956f3f1a37dd34ab7f6a59cb78ae1acc7388951ec3777b52beff1fa8e2bf6426ad46214e724d21
7
+ data.tar.gz: f82218caa4733fec59c17ef9aff190e1617aee3049a16629ecfbc15b0c7e6618f1176f9f2bb26e2e67db0388b5f5dc7f164add84efd09f9e49c0776bb36a690d
@@ -20,6 +20,7 @@
20
20
 
21
21
  require 'async/logger'
22
22
 
23
+ require 'async'
23
24
  require 'async/notification'
24
25
  require 'async/semaphore'
25
26
 
@@ -32,17 +33,25 @@ module Async
32
33
 
33
34
  def initialize(constructor, limit: nil)
34
35
  @resources = {}
35
- @available = Async::Notification.new
36
+
37
+ @available = []
38
+ @notification = Async::Notification.new
36
39
 
37
40
  @limit = limit
38
41
 
39
42
  @constructor = constructor
40
43
  @guard = Async::Semaphore.new(1)
44
+
45
+ @gardener = nil
41
46
  end
42
47
 
43
48
  # @attr [Hash<Resource, Integer>] all allocated resources, and their associated usage.
44
49
  attr :resources
45
50
 
51
+ def size
52
+ @resources.size
53
+ end
54
+
46
55
  # Whether the pool has any active resources.
47
56
  def active?
48
57
  !@resources.empty?
@@ -59,7 +68,7 @@ module Async
59
68
 
60
69
  # Wait until a pool resource has been freed.
61
70
  def wait
62
- @available.wait
71
+ @notification.wait
63
72
  end
64
73
 
65
74
  def empty?
@@ -91,6 +100,8 @@ module Async
91
100
  def close
92
101
  @resources.each_key(&:close)
93
102
  @resources.clear
103
+
104
+ @gardener&.stop
94
105
  end
95
106
 
96
107
  def to_s
@@ -131,11 +142,24 @@ module Async
131
142
 
132
143
  resource.close
133
144
 
134
- @available.signal
145
+ @notification.signal
135
146
  end
136
147
 
137
148
  protected
138
149
 
150
+ def start_gardener
151
+ return if @gardener
152
+
153
+ Async(transient: true) do |task|
154
+ @gardener = task
155
+
156
+ Task.yield
157
+ ensure
158
+ @gardener = nil
159
+ self.close
160
+ end
161
+ end
162
+
139
163
  def usage_string
140
164
  "#{@resources.size}/#{@limit || '∞'}"
141
165
  end
@@ -150,52 +174,58 @@ module Async
150
174
  Async.logger.debug(self) {"Reuse #{resource}"}
151
175
 
152
176
  @resources[resource] -= 1
177
+ @available.push(resource)
153
178
 
154
- @available.signal
179
+ @notification.signal
155
180
  end
156
181
 
157
182
  def wait_for_resource
158
183
  # If we fail to create a resource (below), we will end up waiting for one to become resources.
159
184
  until resource = available_resource
160
- @available.wait
185
+ @notification.wait
161
186
  end
162
187
 
163
- Async.logger.debug(self) {"Wait for resource #{resource}"}
188
+ Async.logger.debug(self) {"Wait for resource -> #{resource}"}
164
189
 
165
190
  # if resource.concurrency > 1
166
- # @available.signal
191
+ # @notification.signal
167
192
  # end
168
193
 
169
194
  return resource
170
195
  end
171
196
 
172
197
  def create_resource
198
+ self.start_gardener
199
+
173
200
  # This might return nil, which means creating the resource failed.
174
201
  if resource = @constructor.call
175
202
  @resources[resource] = 1
203
+
204
+ @available.push(resource) if resource.concurrency > 1
176
205
  end
177
206
 
178
207
  return resource
179
208
  end
180
209
 
181
210
  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
211
+ @guard.acquire do
212
+ while resource = @available.last
213
+ if usage = @resources[resource] and usage < resource.concurrency
214
+ if resource.viable?
215
+ @resources[resource] += 1
216
+
217
+ return resource
218
+ else
219
+ retire(resource)
220
+ @available.pop
221
+ end
190
222
  else
191
- retire(resource)
223
+ @available.pop
192
224
  end
193
225
  end
194
- end
195
-
196
- @guard.acquire do
226
+
197
227
  if @limit.nil? or @resources.size < @limit
198
- Async.logger.debug(self) {"No resources resources, allocating new one..."}
228
+ Async.logger.debug(self) {"No available resources, allocating new one..."}
199
229
 
200
230
  return create_resource
201
231
  end
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Async
22
22
  module Pool
23
- VERSION = "0.1.0"
23
+ VERSION = "0.3.3"
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-pool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-22 00:00:00.000000000 Z
11
+ date: 2020-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.8'
19
+ version: '1.25'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.8'
26
+ version: '1.25'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: async-rspec
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.1'
41
41
  - !ruby/object:Gem::Dependency
42
- name: covered
42
+ name: bake-bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: bundler
56
+ name: bake-modernize
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,21 +67,21 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rspec
70
+ name: bundler
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '3.6'
75
+ version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '3.6'
82
+ version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rake
84
+ name: covered
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -94,29 +94,36 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- description:
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.6'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.6'
111
+ description:
98
112
  email:
99
- - samuel.williams@oriontransfer.co.nz
100
113
  executables: []
101
114
  extensions: []
102
115
  extra_rdoc_files: []
103
116
  files:
104
- - ".editorconfig"
105
- - ".gitignore"
106
- - ".rspec"
107
- - ".travis.yml"
108
- - Gemfile
109
- - README.md
110
- - Rakefile
111
- - async-pool.gemspec
112
117
  - lib/async/pool.rb
113
118
  - lib/async/pool/controller.rb
114
119
  - lib/async/pool/resource.rb
115
120
  - lib/async/pool/version.rb
116
121
  homepage: https://github.com/socketry/async-pool
117
- licenses: []
118
- metadata: {}
119
- post_install_message:
122
+ licenses:
123
+ - MIT
124
+ metadata:
125
+ funding_uri: https://github.com/sponsors/ioquatix/
126
+ post_install_message:
120
127
  rdoc_options: []
121
128
  require_paths:
122
129
  - lib
@@ -124,15 +131,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
124
131
  requirements:
125
132
  - - ">="
126
133
  - !ruby/object:Gem::Version
127
- version: '0'
134
+ version: '2.5'
128
135
  required_rubygems_version: !ruby/object:Gem::Requirement
129
136
  requirements:
130
137
  - - ">="
131
138
  - !ruby/object:Gem::Version
132
139
  version: '0'
133
140
  requirements: []
134
- rubygems_version: 3.0.4
135
- signing_key:
141
+ rubygems_version: 3.1.2
142
+ signing_key:
136
143
  specification_version: 4
137
- summary: A Redis client library.
144
+ summary: A singleplex and multiplex resource pool for implementing robust clients.
138
145
  test_files: []
@@ -1,6 +0,0 @@
1
- root = true
2
-
3
- [*]
4
- indent_style = tab
5
- indent_size = 2
6
-
data/.gitignore DELETED
@@ -1,13 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
-
11
- # rspec failure tracking
12
- .rspec_status
13
- .covered.db
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --warnings
3
- --require spec_helper
@@ -1,20 +0,0 @@
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 DELETED
@@ -1,3 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
data/README.md DELETED
@@ -1,72 +0,0 @@
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 DELETED
@@ -1,6 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new
5
-
6
- task :default => :spec
@@ -1,28 +0,0 @@
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