async-limiter 1.5.4 → 2.0.0

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/context/generic-limiter.md +167 -0
  4. data/context/getting-started.md +226 -0
  5. data/context/index.yaml +41 -0
  6. data/context/limited-limiter.md +184 -0
  7. data/context/queued-limiter.md +109 -0
  8. data/context/timing-strategies.md +666 -0
  9. data/context/token-usage.md +85 -0
  10. data/lib/async/limiter/generic.rb +160 -0
  11. data/lib/async/limiter/limited.rb +103 -0
  12. data/lib/async/limiter/queued.rb +85 -0
  13. data/lib/async/limiter/timing/burst.rb +153 -0
  14. data/lib/async/limiter/timing/fixed_window.rb +42 -0
  15. data/lib/async/limiter/timing/leaky_bucket.rb +146 -0
  16. data/lib/async/limiter/timing/none.rb +56 -0
  17. data/lib/async/limiter/timing/ordered.rb +58 -0
  18. data/lib/async/limiter/timing/sliding_window.rb +152 -0
  19. data/lib/async/limiter/token.rb +102 -0
  20. data/lib/async/limiter/version.rb +10 -3
  21. data/lib/async/limiter.rb +21 -7
  22. data/lib/metrics/provider/async/limiter/generic.rb +74 -0
  23. data/lib/metrics/provider/async/limiter.rb +7 -0
  24. data/lib/traces/provider/async/limiter/generic.rb +41 -0
  25. data/lib/traces/provider/async/limiter.rb +7 -0
  26. data/license.md +25 -0
  27. data/readme.md +45 -0
  28. data/releases.md +50 -0
  29. data.tar.gz.sig +0 -0
  30. metadata +68 -83
  31. metadata.gz.sig +0 -0
  32. data/lib/async/limiter/concurrent.rb +0 -101
  33. data/lib/async/limiter/constants.rb +0 -6
  34. data/lib/async/limiter/unlimited.rb +0 -53
  35. data/lib/async/limiter/window/continuous.rb +0 -21
  36. data/lib/async/limiter/window/fixed.rb +0 -21
  37. data/lib/async/limiter/window/sliding.rb +0 -21
  38. data/lib/async/limiter/window.rb +0 -296
data/license.md ADDED
@@ -0,0 +1,25 @@
1
+ # MIT License
2
+
3
+ Copyright, 2020-2021, by Bruno Sutic.
4
+ Copyright, 2025, by Francisco Mejia.
5
+ Copyright, 2025, by Shopify Inc.
6
+ Copyright, 2025, by Samuel Williams.
7
+ Copyright, 2025, by William T. Nelson.
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
data/readme.md ADDED
@@ -0,0 +1,45 @@
1
+ # Async Limiter
2
+
3
+ A Ruby gem providing flexible concurrency and rate limiting for async applications.
4
+
5
+ [![Development Status](https://github.com/socketry/async-limiter/workflows/Test/badge.svg)](https://github.com/socketry/async-limiter/actions?workflow=Test)
6
+
7
+ ## Usage
8
+
9
+ Please see the [project documentation](https://socketry.github.io/async-limiter/) for more details.
10
+
11
+ - [Getting Started](https://socketry.github.io/async-limiter/guides/getting-started/index) - This guide explains how to get started the `async-limiter` gem for controlling concurrency and rate limiting in Ruby applications.
12
+
13
+ - [Generic Limiter](https://socketry.github.io/async-limiter/guides/generic-limiter/index) - This guide explains the <code class="language-ruby">Async::Limiter::Generic</code> class, which provides unlimited concurrency by default and serves as the base implementation for all other limiters. It's ideal when you need timing constraints without concurrency limits, or when building custom limiter implementations.
14
+
15
+ - [Limited Limiter](https://socketry.github.io/async-limiter/guides/limited-limiter/index) - This guide explains the <code class="language-ruby">Async::Limiter::Limited</code> class, which provides semaphore-style concurrency control, enforcing a maximum number of concurrent operations. It's perfect for controlling concurrency when you have limited capacity or want to prevent system overload.
16
+
17
+ - [Queued Limiter](https://socketry.github.io/async-limiter/guides/queued-limiter/index) - This guide explains the <code class="language-ruby">Async::Limiter::Queued</code> class, which provides priority-based task scheduling with optional resource management. Its key feature is priority-based acquisition where higher priority tasks get access first, with optional support for distributing specific resources from a pre-populated queue.
18
+
19
+ - [Timing Strategies](https://socketry.github.io/async-limiter/guides/timing-strategies/index) - This guide explains how to use timing strategies to provide rate limiting and timing constraints that can be combined with any limiter. They control *when* operations can execute, while limiters control *how many* can execute concurrently.
20
+
21
+ - [Token Usage](https://socketry.github.io/async-limiter/guides/token-usage/index) - This guide explains how to use tokens for advanced resource management with `async-limiter`. Tokens provide sophisticated resource handling with support for re-acquisition and automatic cleanup.
22
+
23
+ ## See Also
24
+
25
+ - [falcon](https://github.com/socketry/falcon) - A high-performance web server
26
+ - [async-http](https://github.com/socketry/async-http) - Asynchronous HTTP client and server
27
+ - [async](https://github.com/socketry/async) - The core async framework
28
+
29
+ ## Contributing
30
+
31
+ We welcome contributions to this project.
32
+
33
+ 1. Fork it.
34
+ 2. Create your feature branch (`git checkout -b my-new-feature`).
35
+ 3. Commit your changes (`git commit -am 'Add some feature'`).
36
+ 4. Push to the branch (`git push origin my-new-feature`).
37
+ 5. Create new Pull Request.
38
+
39
+ ### Developer Certificate of Origin
40
+
41
+ In order to protect users of this project, we require all contributors to comply with the [Developer Certificate of Origin](https://developercertificate.org/). This ensures that all contributions are properly licensed and attributed.
42
+
43
+ ### Community Guidelines
44
+
45
+ This project is best served by a collaborative and respectful environment. Treat each other professionally, respect differing viewpoints, and engage constructively. Harassment, discrimination, or harmful behavior is not tolerated. Communicate clearly, listen actively, and support one another. If any issues arise, please inform the project maintainers.
data/releases.md ADDED
@@ -0,0 +1,50 @@
1
+ # Releases
2
+
3
+ ## v2.0.0
4
+
5
+ The 2.0.x release should be considered somewhat unstable.
6
+
7
+ - **Breaking**: Complete API redesign. The v1.x classes (`Async::Limiter::Concurrent`, `Async::Limiter::Unlimited`, etc.) have been replaced with a new inheritance-based architecture.
8
+ - **Breaking**: Removed `blocking?` method due to inherent race conditions. Use `acquire(timeout: 0)` for non-blocking checks.
9
+ - **Breaking**: Timing strategies now use consumption-only model (no explicit `release` methods).
10
+ - **Breaking**: Window classes moved from `limiter/window/` to `limiter/timing/` with renamed classes.
11
+
12
+ ### New Architecture (replaces v1.x classes)
13
+
14
+ - **New**: `Async::Limiter::Generic` - Unlimited concurrency with timing coordination (replaces `Async::Limiter::Unlimited`).
15
+ - **New**: `Async::Limiter::Limited` - Counting semaphore with configurable limits (replaces `Async::Limiter::Concurrent`).
16
+ - **New**: `Async::Limiter::Queued` - Queue-based resource distribution with priority/timeout support (completely new functionality).
17
+
18
+ ### Advanced Timeout Features
19
+
20
+ - **New**: Unified timeout API - `acquire(timeout: 0/nil/seconds)` provides non-blocking and timed acquisition.
21
+ - **New**: Precise deadline tracking using `Async::Deadline` (requires async v2.31.0+).
22
+ - **New**: Convoy effect prevention - quick timeout operations not blocked by slow operations.
23
+ - **New**: Accurate timeout propagation - remaining time correctly passed through timing and concurrency layers.
24
+
25
+ ### Cost-Based Acquisition
26
+
27
+ - **New**: Cost-based acquisition - `acquire(cost: 1.5)` for proportional resource consumption.
28
+ - **New**: Starvation prevention - validates cost against timing strategy `maximum_cost` capacity.
29
+ - **New**: Flexible operation weighting - light operations consume fewer resources than heavy ones.
30
+
31
+ ### Enhanced Timing Strategies
32
+
33
+ - Add `Async::Limiter::Timing::LeakyBucket` for token bucket rate limiting with automatic leaking.
34
+ - Add `Async::Limiter::Timing::FixedWindow` for discrete time boundary enforcement.
35
+ - Rename `Async::Limiter::Timing::Window` to `Async::Limiter::Timing::SlidingWindow` for clarity.
36
+ - **Breaking**: Remove `release` methods from timing strategies (consumption-only model).
37
+ - **Breaking**: Remove `try_acquire` methods from timing strategies (unified timeout API).
38
+
39
+ ### Token-Based Resource Management
40
+
41
+ - **New**: `acquire_token` method returns `Token` objects for advanced resource management.
42
+ - **New**: Token re-acquisition with different options - `token.acquire(priority: 5)`.
43
+ - **New**: Automatic token cleanup with block usage.
44
+
45
+ ### Thread Safety and Performance
46
+
47
+ - **New**: Race condition elimination by moving timing coordination inside mutex.
48
+ - **New**: Fast path optimizations using `deadline.expired?` checks.
49
+ - **New**: Atomic timing coordination prevents race conditions in concurrent access.
50
+ - **Improved**: Test performance using time simulation instead of actual sleep calls.
data.tar.gz.sig ADDED
Binary file
metadata CHANGED
@@ -1,14 +1,46 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-limiter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.4
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bruno Sutic
8
- autorequire:
8
+ - Shopify Inc.
9
+ - Samuel Williams
10
+ - Francisco Mejia
11
+ - William
9
12
  bindir: bin
10
- cert_chain: []
11
- date: 2021-12-30 00:00:00.000000000 Z
13
+ cert_chain:
14
+ - |
15
+ -----BEGIN CERTIFICATE-----
16
+ MIIE2DCCA0CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMRgwFgYDVQQDDA9zYW11
17
+ ZWwud2lsbGlhbXMxHTAbBgoJkiaJk/IsZAEZFg1vcmlvbnRyYW5zZmVyMRIwEAYK
18
+ CZImiZPyLGQBGRYCY28xEjAQBgoJkiaJk/IsZAEZFgJuejAeFw0yMjA4MDYwNDUz
19
+ MjRaFw0zMjA4MDMwNDUzMjRaMGExGDAWBgNVBAMMD3NhbXVlbC53aWxsaWFtczEd
20
+ MBsGCgmSJomT8ixkARkWDW9yaW9udHJhbnNmZXIxEjAQBgoJkiaJk/IsZAEZFgJj
21
+ bzESMBAGCgmSJomT8ixkARkWAm56MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
22
+ igKCAYEAomvSopQXQ24+9DBB6I6jxRI2auu3VVb4nOjmmHq7XWM4u3HL+pni63X2
23
+ 9qZdoq9xt7H+RPbwL28LDpDNflYQXoOhoVhQ37Pjn9YDjl8/4/9xa9+NUpl9XDIW
24
+ sGkaOY0eqsQm1pEWkHJr3zn/fxoKPZPfaJOglovdxf7dgsHz67Xgd/ka+Wo1YqoE
25
+ e5AUKRwUuvaUaumAKgPH+4E4oiLXI4T1Ff5Q7xxv6yXvHuYtlMHhYfgNn8iiW8WN
26
+ XibYXPNP7NtieSQqwR/xM6IRSoyXKuS+ZNGDPUUGk8RoiV/xvVN4LrVm9upSc0ss
27
+ RZ6qwOQmXCo/lLcDUxJAgG95cPw//sI00tZan75VgsGzSWAOdjQpFM0l4dxvKwHn
28
+ tUeT3ZsAgt0JnGqNm2Bkz81kG4A2hSyFZTFA8vZGhp+hz+8Q573tAR89y9YJBdYM
29
+ zp0FM4zwMNEUwgfRzv1tEVVUEXmoFCyhzonUUw4nE4CFu/sE3ffhjKcXcY//qiSW
30
+ xm4erY3XAgMBAAGjgZowgZcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O
31
+ BBYEFO9t7XWuFf2SKLmuijgqR4sGDlRsMC4GA1UdEQQnMCWBI3NhbXVlbC53aWxs
32
+ aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MC4GA1UdEgQnMCWBI3NhbXVlbC53aWxs
33
+ aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MA0GCSqGSIb3DQEBCwUAA4IBgQB5sxkE
34
+ cBsSYwK6fYpM+hA5B5yZY2+L0Z+27jF1pWGgbhPH8/FjjBLVn+VFok3CDpRqwXCl
35
+ xCO40JEkKdznNy2avOMra6PFiQyOE74kCtv7P+Fdc+FhgqI5lMon6tt9rNeXmnW/
36
+ c1NaMRdxy999hmRGzUSFjozcCwxpy/LwabxtdXwXgSay4mQ32EDjqR1TixS1+smp
37
+ 8C/NCWgpIfzpHGJsjvmH2wAfKtTTqB9CVKLCWEnCHyCaRVuKkrKjqhYCdmMBqCws
38
+ JkxfQWC+jBVeG9ZtPhQgZpfhvh+6hMhraUYRQ6XGyvBqEUe+yo6DKIT3MtGE2+CP
39
+ eX9i9ZWBydWb8/rvmwmX2kkcBbX0hZS1rcR593hGc61JR6lvkGYQ2MYskBveyaxt
40
+ Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
41
+ voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
42
+ -----END CERTIFICATE-----
43
+ date: 1980-01-02 00:00:00.000000000 Z
12
44
  dependencies:
13
45
  - !ruby/object:Gem::Dependency
14
46
  name: async
@@ -16,96 +48,50 @@ dependencies:
16
48
  requirements:
17
49
  - - ">="
18
50
  - !ruby/object:Gem::Version
19
- version: '1.27'
20
- - - "<"
21
- - !ruby/object:Gem::Version
22
- version: '3.0'
51
+ version: '2.31'
23
52
  type: :runtime
24
53
  prerelease: false
25
54
  version_requirements: !ruby/object:Gem::Requirement
26
55
  requirements:
27
56
  - - ">="
28
57
  - !ruby/object:Gem::Version
29
- version: '1.27'
30
- - - "<"
31
- - !ruby/object:Gem::Version
32
- version: '3.0'
33
- - !ruby/object:Gem::Dependency
34
- name: async-rspec
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: '1.15'
40
- type: :development
41
- prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - "~>"
45
- - !ruby/object:Gem::Version
46
- version: '1.15'
47
- - !ruby/object:Gem::Dependency
48
- name: rspec
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '3.10'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '3.10'
61
- - !ruby/object:Gem::Dependency
62
- name: rubocop-rspec
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '2.0'
68
- type: :development
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '2.0'
75
- - !ruby/object:Gem::Dependency
76
- name: standard
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - "~>"
80
- - !ruby/object:Gem::Version
81
- version: '0.9'
82
- type: :development
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '0.9'
89
- description:
90
- email: code@brunosutic.com
58
+ version: '2.31'
91
59
  executables: []
92
60
  extensions: []
93
61
  extra_rdoc_files: []
94
62
  files:
63
+ - context/generic-limiter.md
64
+ - context/getting-started.md
65
+ - context/index.yaml
66
+ - context/limited-limiter.md
67
+ - context/queued-limiter.md
68
+ - context/timing-strategies.md
69
+ - context/token-usage.md
95
70
  - lib/async/limiter.rb
96
- - lib/async/limiter/concurrent.rb
97
- - lib/async/limiter/constants.rb
98
- - lib/async/limiter/unlimited.rb
71
+ - lib/async/limiter/generic.rb
72
+ - lib/async/limiter/limited.rb
73
+ - lib/async/limiter/queued.rb
74
+ - lib/async/limiter/timing/burst.rb
75
+ - lib/async/limiter/timing/fixed_window.rb
76
+ - lib/async/limiter/timing/leaky_bucket.rb
77
+ - lib/async/limiter/timing/none.rb
78
+ - lib/async/limiter/timing/ordered.rb
79
+ - lib/async/limiter/timing/sliding_window.rb
80
+ - lib/async/limiter/token.rb
99
81
  - lib/async/limiter/version.rb
100
- - lib/async/limiter/window.rb
101
- - lib/async/limiter/window/continuous.rb
102
- - lib/async/limiter/window/fixed.rb
103
- - lib/async/limiter/window/sliding.rb
82
+ - lib/metrics/provider/async/limiter.rb
83
+ - lib/metrics/provider/async/limiter/generic.rb
84
+ - lib/traces/provider/async/limiter.rb
85
+ - lib/traces/provider/async/limiter/generic.rb
86
+ - license.md
87
+ - readme.md
88
+ - releases.md
104
89
  homepage: https://github.com/bruno-/async-limiter
105
90
  licenses:
106
91
  - MIT
107
- metadata: {}
108
- post_install_message:
92
+ metadata:
93
+ documentation_uri: https://socketry.github.io/async-limiter/
94
+ source_code_uri: https://github.com/socketry/async-limiter.git
109
95
  rdoc_options: []
110
96
  require_paths:
111
97
  - lib
@@ -113,15 +99,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
99
  requirements:
114
100
  - - ">="
115
101
  - !ruby/object:Gem::Version
116
- version: 2.7.0
102
+ version: '3.2'
117
103
  required_rubygems_version: !ruby/object:Gem::Requirement
118
104
  requirements:
119
105
  - - ">="
120
106
  - !ruby/object:Gem::Version
121
107
  version: '0'
122
108
  requirements: []
123
- rubygems_version: 3.2.3
124
- signing_key:
109
+ rubygems_version: 3.6.9
125
110
  specification_version: 4
126
- summary: Async limiters
111
+ summary: Execution rate limiting for Async
127
112
  test_files: []
metadata.gz.sig ADDED
Binary file
@@ -1,101 +0,0 @@
1
- require "async/task"
2
- require_relative "constants"
3
-
4
- module Async
5
- module Limiter
6
- class Concurrent
7
- attr_reader :count
8
-
9
- attr_reader :limit
10
-
11
- def initialize(limit = 1, parent: nil, queue: [])
12
- @count = 0
13
- @limit = limit
14
- @waiting = queue
15
- @parent = parent
16
-
17
- validate!
18
- end
19
-
20
- def blocking?
21
- limit_blocking?
22
- end
23
-
24
- def async(*queue_args, parent: (@parent || Task.current), **options)
25
- acquire(*queue_args)
26
- parent.async(**options) do |task|
27
- yield task
28
- ensure
29
- release
30
- end
31
- end
32
-
33
- def sync(*queue_args)
34
- acquire(*queue_args) do
35
- yield(@parent || Task.current)
36
- end
37
- end
38
-
39
- def acquire(*queue_args)
40
- wait(*queue_args)
41
- @count += 1
42
-
43
- return unless block_given?
44
-
45
- begin
46
- yield
47
- ensure
48
- release
49
- end
50
- end
51
-
52
- def release
53
- @count -= 1
54
-
55
- resume_waiting
56
- end
57
-
58
- def limit=(new_limit)
59
- validate_limit!(new_limit)
60
-
61
- @limit = new_limit
62
- end
63
-
64
- private
65
-
66
- def limit_blocking?
67
- @count >= @limit
68
- end
69
-
70
- def wait(*queue_args)
71
- fiber = Fiber.current
72
-
73
- if blocking?
74
- @waiting.push(fiber, *queue_args) # queue_args used for custom queues
75
- Task.yield while blocking?
76
- end
77
- rescue Exception # rubocop:disable Lint/RescueException
78
- @waiting.delete(fiber)
79
- raise
80
- end
81
-
82
- def resume_waiting
83
- while !blocking? && (fiber = @waiting.shift)
84
- fiber.resume if fiber.alive?
85
- end
86
- end
87
-
88
- def validate!
89
- if @limit.finite? && (@limit % 1).nonzero?
90
- raise ArgumentError, "limit must be a whole number"
91
- end
92
-
93
- validate_limit!
94
- end
95
-
96
- def validate_limit!(value = @limit)
97
- raise ArgumentError, "limit must be greater than 1" if value < 1
98
- end
99
- end
100
- end
101
- end
@@ -1,6 +0,0 @@
1
- module Async
2
- module Limiter
3
- Error = Class.new(StandardError)
4
- ArgumentError = Class.new(Error)
5
- end
6
- end
@@ -1,53 +0,0 @@
1
- require "async/task"
2
-
3
- module Async
4
- module Limiter
5
- class Unlimited
6
- attr_reader :count
7
-
8
- def initialize(parent: nil)
9
- @count = 0
10
- @parent = parent
11
- end
12
-
13
- def limit
14
- Float::INFINITY
15
- end
16
-
17
- def blocking?
18
- false
19
- end
20
-
21
- def async(parent: (@parent || Task.current), **options)
22
- acquire
23
- parent.async(**options) do |task|
24
- yield task
25
- ensure
26
- release
27
- end
28
- end
29
-
30
- def sync(*queue_args)
31
- acquire(*queue_args) do
32
- yield(@parent || Task.current)
33
- end
34
- end
35
-
36
- def acquire
37
- @count += 1
38
-
39
- return unless block_given?
40
-
41
- begin
42
- yield
43
- ensure
44
- release
45
- end
46
- end
47
-
48
- def release
49
- @count -= 1
50
- end
51
- end
52
- end
53
- end
@@ -1,21 +0,0 @@
1
- require_relative "../window"
2
-
3
- module Async
4
- module Limiter
5
- class Window
6
- class Continuous < Window
7
- def initialize(limit = 1, window: 1, parent: nil, lock: true, queue: [])
8
- super(
9
- limit,
10
- type: :sliding, # type doesn't matter, but sliding is less work
11
- burstable: false,
12
- window: window,
13
- parent: parent,
14
- lock: lock,
15
- queue: queue
16
- )
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,21 +0,0 @@
1
- require_relative "../window"
2
-
3
- module Async
4
- module Limiter
5
- class Window
6
- class Fixed < Window
7
- def initialize(limit = 1, window: 1, parent: nil, lock: true, queue: [])
8
- super(
9
- limit,
10
- type: :fixed,
11
- burstable: true,
12
- window: window,
13
- parent: parent,
14
- lock: lock,
15
- queue: queue
16
- )
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,21 +0,0 @@
1
- require_relative "../window"
2
-
3
- module Async
4
- module Limiter
5
- class Window
6
- class Sliding < Window
7
- def initialize(limit = 1, window: 1, parent: nil, lock: true, queue: [])
8
- super(
9
- limit,
10
- type: :sliding,
11
- burstable: true,
12
- window: window,
13
- parent: parent,
14
- lock: lock,
15
- queue: queue
16
- )
17
- end
18
- end
19
- end
20
- end
21
- end