async-tools 0.2.2 → 0.2.4

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: 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