async-pool 0.7.1 → 0.8.1

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: cfc00b6087965cc5fc3f58ae151a0048fc8cf351aab9c06bdaf46b0eb65bb877
4
- data.tar.gz: 7f9e3067d5bc75de995735ac4a025cb6cea4ee72e0e63201ec4f28c000301cc2
3
+ metadata.gz: 8d877fb908af8482011de394630982c4c593e36a5efd9ef19a885bba5774f6e8
4
+ data.tar.gz: be2d7efd8c65a9eec5237acc4f432e76a3f401da0b13e7e10b089f9849382f2a
5
5
  SHA512:
6
- metadata.gz: e6933852df812446375faf0c0c921c137bdd972beec9f1e392f6bdfc0c803ddf1cf62151323fbd18f8431c9ab1021eaac2c90ab461f03679d3e93cebfbc039b0
7
- data.tar.gz: 76a83cc5cc6a5dc2230ae6ad3eedc12a0e4fc24170d7391d5a1c032553d4a5653fc89b12060e331bd64687fefb5308d64785bbdc9cc70701b3f86e394de718f2
6
+ metadata.gz: 3e472af40018c10b2a8d726fc31b04ea96557d790c55e4fe6449a891b048c96da66794926eb7ca726195f778d0bea1e6c9d762b274a06a0922f382d5a8794ab7
7
+ data.tar.gz: 8abacfdcb4b32eb573e0108aecdbdd7ff385386e8a8de2710550b976a81467286e73fa8f36292162e801d5f000fc2a222aabf99f7cf334a35d7e22e47833ded1
checksums.yaml.gz.sig CHANGED
Binary file
@@ -11,6 +11,9 @@ require 'async'
11
11
  require 'async/notification'
12
12
  require 'async/semaphore'
13
13
 
14
+ require 'traces'
15
+ require 'metrics'
16
+
14
17
  module Async
15
18
  module Pool
16
19
  # A resource pool controller.
@@ -154,20 +157,20 @@ module Async
154
157
  retire(resource) unless processed
155
158
  end
156
159
 
157
- # Close all resources in the pool.
158
- def close
159
- @available.clear
160
+ def drain
161
+ Console.debug(self, "Draining pool...", size: @resources.size)
160
162
 
161
- while pair = @resources.shift
162
- resource, usage = pair
163
-
164
- if usage > 0
165
- Console.warn(self, resource: resource, usage: usage) {"Closing resource while still in use!"}
166
- end
167
-
168
- resource.close
163
+ # Enumerate all existing resources and retire them:
164
+ while resource = acquire_existing_resource
165
+ retire(resource)
169
166
  end
167
+ end
168
+
169
+ # Close all resources in the pool.
170
+ def close
171
+ self.drain
170
172
 
173
+ @available.clear
171
174
  @gardener&.stop
172
175
  end
173
176
 
@@ -224,6 +227,8 @@ module Async
224
227
  def start_gardener
225
228
  return if @gardener
226
229
 
230
+ @gardener = true
231
+
227
232
  Async(transient: true, annotation: "#{self.class} Gardener") do |task|
228
233
  @gardener = task
229
234
 
@@ -262,6 +267,7 @@ module Async
262
267
 
263
268
  def reuse(resource)
264
269
  Console.debug(self) {"Reuse #{resource}"}
270
+
265
271
  usage = @resources[resource]
266
272
 
267
273
  if usage.nil? || usage.zero?
@@ -286,11 +292,7 @@ module Async
286
292
  @notification.wait
287
293
  end
288
294
 
289
- Console.debug(self) {"Wait for resource -> #{resource}"}
290
-
291
- # if resource.concurrency > 1
292
- # @notification.signal
293
- # end
295
+ # Be careful not to context switch or fail here.
294
296
 
295
297
  return resource
296
298
  end
@@ -318,19 +320,40 @@ module Async
318
320
  def available_resource
319
321
  resource = nil
320
322
 
323
+ Console.debug(self, "Acquiring concurrency guard...", blocking: @guard.blocking?)
324
+
321
325
  @guard.acquire do
322
- resource = get_resource
326
+ Console.debug(self, "Acquired concurrency guard.")
327
+
328
+ resource = acquire_or_create_resource
323
329
  end
324
330
 
325
331
  return resource
326
- rescue Exception
332
+ rescue Exception => error
327
333
  reuse(resource) if resource
328
334
  raise
329
335
  end
330
336
 
331
337
  private
332
338
 
333
- def get_resource
339
+ # Acquire an existing resource with zero usage.
340
+ # If there are resources that are in use, wait until they are released.
341
+ def acquire_existing_resource
342
+ while @resources.any?
343
+ @resources.each do |resource, usage|
344
+ if usage == 0
345
+ return resource
346
+ end
347
+ end
348
+
349
+ @notification.wait
350
+ end
351
+
352
+ # Only when the pool has been completely drained, return nil:
353
+ return nil
354
+ end
355
+
356
+ def acquire_or_create_resource
334
357
  while resource = @available.last
335
358
  if usage = @resources[resource] and usage < resource.concurrency
336
359
  if resource.viable?
@@ -358,6 +381,50 @@ module Async
358
381
  return create_resource
359
382
  end
360
383
  end
384
+
385
+ Traces::Provider(self) do
386
+ def create_resource(...)
387
+ attributes = {
388
+ concurrency: @guard.limit,
389
+ size: @resources.size,
390
+ limit: @limit,
391
+ }
392
+
393
+ Traces.trace('async.pool.create', attributes: attributes) {super}
394
+ end
395
+
396
+ def drain(...)
397
+ attributes = {
398
+ size: @resources.size,
399
+ }
400
+
401
+ Traces.trace('async.pool.drain', attributes: attributes) {super}
402
+ end
403
+ end
404
+
405
+ Metrics::Provider(self) do
406
+ ACQUIRE_COUNT = Metrics.metric('async.pool.acquire', :counter, description: 'Number of times a resource was invoked.')
407
+ RELEASE_COUNT = Metrics.metric('async.pool.release', :counter, description: 'Number of times a resource was released.')
408
+ RETIRE_COUNT = Metrics.metric('async.pool.retire', :counter, description: 'Number of times a resource was retired.')
409
+
410
+ def acquire(...)
411
+ ACQUIRE_COUNT.emit(1)
412
+
413
+ super
414
+ end
415
+
416
+ def release(...)
417
+ super.tap do
418
+ RELEASE_COUNT.emit(1)
419
+ end
420
+ end
421
+
422
+ def retire(...)
423
+ super.tap do
424
+ RETIRE_COUNT.emit(1)
425
+ end
426
+ end
427
+ end
361
428
  end
362
429
  end
363
430
  end
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Async
7
7
  module Pool
8
- VERSION = "0.7.1"
8
+ VERSION = "0.8.1"
9
9
  end
10
10
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-pool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -40,7 +40,7 @@ cert_chain:
40
40
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
41
41
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
42
42
  -----END CERTIFICATE-----
43
- date: 2024-08-03 00:00:00.000000000 Z
43
+ date: 2024-08-26 00:00:00.000000000 Z
44
44
  dependencies:
45
45
  - !ruby/object:Gem::Dependency
46
46
  name: async
@@ -56,6 +56,34 @@ dependencies:
56
56
  - - ">="
57
57
  - !ruby/object:Gem::Version
58
58
  version: '1.25'
59
+ - !ruby/object:Gem::Dependency
60
+ name: metrics
61
+ requirement: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ - !ruby/object:Gem::Dependency
74
+ name: traces
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ type: :runtime
81
+ prerelease: false
82
+ version_requirements: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
59
87
  description:
60
88
  email:
61
89
  executables: []
metadata.gz.sig CHANGED
Binary file