Class: Async::Limiter::Generic
- Inherits:
-
Object
- Object
- Async::Limiter::Generic
- Defined in:
- lib/async/limiter/generic.rb
Overview
Generic limiter class with unlimited concurrency by default.
This provides the foundation for rate limiting and concurrency control. Subclasses can override methods to implement specific limiting behaviors.
The Generic limiter coordinates timing strategies with concurrency control, providing thread-safe acquisition with deadline tracking and cost-based consumption.
Instance Attribute Summary collapse
- #Registry-like object for utilization metrics. ⇒ Object readonly
-
#tags ⇒ Object
readonly
Returns the value of attribute tags.
- #Tags associated with this limiter for identification or categorization.(associatedwiththislimiter) ⇒ Object readonly
-
#utilization ⇒ Object
readonly
Returns the value of attribute utilization.
Instance Method Summary collapse
-
#acquire(timeout: nil, cost: 1, **options) ⇒ Object
Manually acquire a resource with timing and concurrency coordination.
-
#as_json ⇒ Object
Get a JSON-compatible representation of the limiter statistics.
-
#async(parent: (@parent || Task.current), **options) ⇒ Object
Execute a task asynchronously with unlimited concurrency.
-
#initialize(timing: Timing::None, parent: nil, tags: nil, utilization: Async::Utilization::Registry.new) ⇒ Generic
constructor
Initialize a new generic limiter.
- #limited? ⇒ Boolean
-
#release(resource = true) ⇒ Object
Release a previously acquired resource.
-
#statistics ⇒ Object
Get current limiter statistics.
-
#sync ⇒ Object
Execute a task synchronously with unlimited concurrency.
-
#to_json ⇒ Object
Get a JSON string representation of the limiter statistics.
Constructor Details
#initialize(timing: Timing::None, parent: nil, tags: nil, utilization: Async::Utilization::Registry.new) ⇒ Generic
Initialize a new generic limiter.
29 30 31 32 33 34 35 36 |
# File 'lib/async/limiter/generic.rb', line 29 def initialize(timing: Timing::None, parent: nil, tags: nil, utilization: Async::Utilization::Registry.new) @timing = timing @parent = parent @tags = @utilization = utilization @mutex = Mutex.new end |
Instance Attribute Details
#Registry-like object for utilization metrics. ⇒ Object (readonly)
42 |
# File 'lib/async/limiter/generic.rb', line 42 attr :utilization |
#tags ⇒ Object (readonly)
Returns the value of attribute tags.
39 40 41 |
# File 'lib/async/limiter/generic.rb', line 39 def @tags end |
#Tags associated with this limiter for identification or categorization.(associatedwiththislimiter) ⇒ Object (readonly)
39 |
# File 'lib/async/limiter/generic.rb', line 39 attr :tags |
#utilization ⇒ Object (readonly)
Returns the value of attribute utilization.
42 43 44 |
# File 'lib/async/limiter/generic.rb', line 42 def utilization @utilization end |
Instance Method Details
#acquire(timeout: nil, cost: 1, **options) ⇒ Object
Manually acquire a resource with timing and concurrency coordination.
This method provides the core acquisition logic with support for:
-
Flexible timeout handling (blocking, non-blocking, timed)
-
Cost-based consumption for timing strategies
-
Deadline tracking to prevent timeout violations
-
Automatic resource cleanup with block usage
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/async/limiter/generic.rb', line 92 def acquire(timeout: nil, cost: 1, **) # Validate cost against timing strategy capacity: maximum_cost = @timing.maximum_cost if cost > maximum_cost raise ArgumentError, "Cost #{cost} exceeds maximum supported cost #{maximum_cost} for timing strategy!" end resource = nil deadline = Deadline.start(timeout) # Atomically handle timing constraints and concurrency logic: acquire_synchronized(timeout, cost, **) do # Wait for timing constraints to be satisfied (mutex released during sleep) return nil unless @timing.wait(@mutex, deadline, cost) # Execute the concurrency-specific acquisition logic resource = acquire_resource(deadline, **) # Record timing acquisition if successful if resource @timing.acquire(cost) else # `acquire_concurrency` should return nil if deadline reached: return nil end resource end return resource unless block_given? begin yield(resource) ensure release(resource) end end |
#as_json ⇒ Object
Get a JSON-compatible representation of the limiter statistics.
147 148 149 |
# File 'lib/async/limiter/generic.rb', line 147 def as_json(...) statistics end |
#async(parent: (@parent || Task.current), **options) ⇒ Object
Execute a task asynchronously with unlimited concurrency.
56 57 58 59 60 61 62 63 |
# File 'lib/async/limiter/generic.rb', line 56 def async(parent: (@parent || Task.current), **) acquire parent.async(**) do |task| yield task ensure release end end |
#limited? ⇒ Boolean
45 46 47 |
# File 'lib/async/limiter/generic.rb', line 45 def limited? false end |
#release(resource = true) ⇒ Object
Release a previously acquired resource.
131 132 133 |
# File 'lib/async/limiter/generic.rb', line 131 def release(resource = true) release_resource(resource) end |
#statistics ⇒ Object
Get current limiter statistics.
137 138 139 140 141 142 143 |
# File 'lib/async/limiter/generic.rb', line 137 def statistics @mutex.synchronize do { timing: @timing.statistics } end end |
#sync ⇒ Object
Execute a task synchronously with unlimited concurrency.
69 70 71 72 73 |
# File 'lib/async/limiter/generic.rb', line 69 def sync acquire do yield(Task.current) end end |
#to_json ⇒ Object
Get a JSON string representation of the limiter statistics.
153 154 155 |
# File 'lib/async/limiter/generic.rb', line 153 def to_json(...) as_json.to_json(...) end |