Class: Async::Limiter::Generic

Inherits:
Object
  • Object
show all
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.

Direct Known Subclasses

Limited, Queued

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(timing: Timing::None, parent: nil, tags: nil) ⇒ Generic

Initialize a new generic limiter.



27
28
29
30
31
32
33
# File 'lib/async/limiter/generic.rb', line 27

def initialize(timing: Timing::None, parent: nil, tags: nil)
	@timing = timing
	@parent = parent
	@tags = tags
	
	@mutex = Mutex.new
end

Instance Attribute Details

#tagsObject (readonly)

Returns the value of attribute tags.



36
37
38
# File 'lib/async/limiter/generic.rb', line 36

def tags
  @tags
end

#Tags associated with this limiter for identification or categorization.(associatedwiththislimiter) ⇒ Object (readonly)



36
# File 'lib/async/limiter/generic.rb', line 36

attr :tags

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



86
87
88
89
90
91
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
# File 'lib/async/limiter/generic.rb', line 86

def acquire(timeout: nil, cost: 1, **options)
	# 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, **options) 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, **options)
		
		# 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_jsonObject

Get a JSON-compatible representation of the limiter statistics.



141
142
143
# File 'lib/async/limiter/generic.rb', line 141

def as_json(...)
	statistics
end

#async(parent: (@parent || Task.current), **options) ⇒ Object

Execute a task asynchronously with unlimited concurrency.



50
51
52
53
54
55
56
57
# File 'lib/async/limiter/generic.rb', line 50

def async(parent: (@parent || Task.current), **options)
	acquire
	parent.async(**options) do |task|
		yield task
	ensure
		release
	end
end

#limited?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/async/limiter/generic.rb', line 39

def limited?
	false
end

#release(resource = true) ⇒ Object

Release a previously acquired resource.



125
126
127
# File 'lib/async/limiter/generic.rb', line 125

def release(resource = true)
	release_resource(resource)
end

#statisticsObject

Get current limiter statistics.



131
132
133
134
135
136
137
# File 'lib/async/limiter/generic.rb', line 131

def statistics
	@mutex.synchronize do
		{
			timing: @timing.statistics
		}
	end
end

#syncObject

Execute a task synchronously with unlimited concurrency.



63
64
65
66
67
# File 'lib/async/limiter/generic.rb', line 63

def sync
	acquire do
		yield(Task.current)
	end
end

#to_jsonObject

Get a JSON string representation of the limiter statistics.



147
148
149
# File 'lib/async/limiter/generic.rb', line 147

def to_json(...)
	as_json.to_json(...)
end