async-tools 0.2.2 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b3b08f9b120bebf744df3e7c0da6e2cb7c8d4c5acb01458c25f8be8ff7588fa
4
- data.tar.gz: 7c02d0bfce7a3bcb21b8ac8b2f4a8aec4bfad5a12233141b7d1d73b139c08684
3
+ metadata.gz: ec1be570dca6a72219f3a39a96a7df91da1783ac2eeff110797f924a3fea3f5e
4
+ data.tar.gz: f16ce65bc17d3652f6e89eb44a95c9f07ba9fd6852328d317d0a023bdaff5138
5
5
  SHA512:
6
- metadata.gz: 496680113c44a54745da6846bca478f426454eaa34c125de569205c9f5fe3bc82ec6fe53589f8c86c0b1222361ec949c7938baa64b2be0246a15da280ca8f30a
7
- data.tar.gz: 14d6d23403ede1040d74e68590ad0572e1c01b402ff6d7d0ff25dfb11c6f0f7a187b894c5681772e7828c88a8ba5f2e95751a3bce58ba9d9dc2aa14c31078e67
6
+ metadata.gz: 13f5d055571394818ed8f3e9e06abd39bcb778a060b489fff53331f572a512089767967b0ba16697a8b024c242cfe55c709ccf5be954e4425e33d58cc7b5c512
7
+ data.tar.gz: 1f79f53e28dccd8355416e9f51ee25cd65df6d8253375853122173caef6cc5173cb5923fab212399fd71d160276c2898ffeae79e32df94ae48cf43465b5f2d36
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- async-tools (0.2.2)
4
+ async-tools (0.2.4)
5
5
  async (~> 2.3)
6
6
  zeitwerk (~> 2.6)
7
7
 
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Async::Cache
4
+ Item = Struct.new("Item", :task, :value, :created_at, :duration) do
5
+ def expired? = created_at && Time.now - created_at >= duration
6
+ end
7
+
8
+ def cache(id, duration:, parent: Async::Task.current)
9
+ cleanup!
10
+ find_or_create(id, duration:) do |item|
11
+ parent.async do |task|
12
+ item.task = task
13
+ item.value = yield(id) if block_given?
14
+ item.created_at = Time.now
15
+ end.wait
16
+ end.value
17
+ end
18
+
19
+ def cleanup! = storage.delete_if { _2.expired? }
20
+ def count = storage.count
21
+
22
+ private
23
+
24
+ def find_or_create(id, duration:)
25
+ storage[id].tap do |item|
26
+ item.duration = duration
27
+ item.task&.wait
28
+ return item if item.created_at
29
+
30
+ yield(item)
31
+ end
32
+ end
33
+
34
+ def storage = @storage ||= Hash.new { _1[_2] = Item.new }
35
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # inspired by https://github.com/negativecode/vines/blob/master/lib/vines/token_bucket.rb
4
+ class Async::Throttler
5
+ def initialize(capacity, rate, parent: Async::Task.current)
6
+ raise ArgumentError, "capacity must be > 0" unless capacity.positive?
7
+ raise ArgumentError, "rate must be > 0" unless rate.positive?
8
+
9
+ @capacity = capacity
10
+ @tokens = capacity
11
+ @rate = rate
12
+ @parent = parent
13
+
14
+ @timestamp = Time.new
15
+ end
16
+
17
+ def wait(timeout: 0)
18
+ with_timeout(timeout) do
19
+ while @tokens < 1
20
+ fill!
21
+ sleep(1.0 / @rate)
22
+ end
23
+ end
24
+
25
+ @tokens -= 1
26
+ end
27
+
28
+ def async(parent: @parent, timeout: 0, &)
29
+ wait(timeout:)
30
+ parent.async(&)
31
+ end
32
+
33
+ private
34
+
35
+ def with_timeout(timeout, &)
36
+ return yield if timeout.zero?
37
+
38
+ Fiber.scheduler.with_timeout(timeout, &)
39
+ end
40
+
41
+ def fill!
42
+ return if @tokens >= @capacity
43
+
44
+ now = Time.new
45
+ @tokens += @rate * (now - @timestamp)
46
+ @tokens = @capacity if @tokens > @capacity
47
+ @timestamp = now
48
+ end
49
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Async # rubocop:disable Style/ClassAndModuleChildren
4
4
  module Tools
5
- VERSION = "0.2.2"
5
+ VERSION = "0.2.4"
6
6
  end
7
7
  end
data/lib/async/tools.rb CHANGED
@@ -22,9 +22,11 @@ module Async
22
22
  end
23
23
  end
24
24
 
25
- def self.map(collection, **params, &)
26
- WorkerPool.with(queue_limit: collection.count, **params) do |pool|
27
- pool.schedule_all(collection, &).map(&:wait)
25
+ def self.map(collection, concurrency: nil, parent: Async::Task.current, &)
26
+ Async::Semaphore.new(concurrency || collection.count, parent:).then do |s|
27
+ collection.map do |item|
28
+ s.async { yield(item) }
29
+ end.map(&:wait)
28
30
  end
29
31
  end
30
32
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gleb Sinyavskiy
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-03-03 00:00:00.000000000 Z
11
+ date: 2023-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -68,10 +68,12 @@ files:
68
68
  - lib/async/app/metrics/server.rb
69
69
  - lib/async/app/metrics/store.rb
70
70
  - lib/async/bus.rb
71
+ - lib/async/cache.rb
71
72
  - lib/async/channel.rb
72
73
  - lib/async/logger.rb
73
74
  - lib/async/q.rb
74
75
  - lib/async/result_notification.rb
76
+ - lib/async/throttler.rb
75
77
  - lib/async/timer.rb
76
78
  - lib/async/tools.rb
77
79
  - lib/async/tools/version.rb