Async limiter for ruby.
Gem async-limiter
.
These limiters are available:
Async:
:Concurrent
Limits running tasks to “x number of tasks at the same time”.
Note: this class has the same logic as
Async::Semaphore.
Example
require "async"
require "async/limiter/concurrent"
Async do
limiter = Async::Limiter::Concurrent.new(2)
4.times do
limiter.async do |task|
task.sleep 1
end
end
end
The above limiter runs two tasks concurrently. After first two tasks are done,
it runs the next two tasks.
The total duration of the above example is 2s.
Notes
Async:
:Fixed
Example
require "async"
require "async/limiter/window/fixed"
Async do
limiter = Async::Limiter::Window::Fixed.new(2, window: 2)
4.times do
limiter.async do |task|
task.sleep 1
end
end
end
The above limiter runs two tasks concurrently at any point in time. After first
two tasks are done it waits for the 2-second window to finish before running
the next two tasks.
The total duration of the above example is a minimum 2s and maximum 3s.
This variation exists because the example can start near the end of the first
2-second window.
Notes
lock: false
onAsync:
:Sliding
Example
require "async"
require "async/limiter/window/sliding"
Async do
limiter = Async::Limiter::Window::Sliding.new(2, window: 2)
4.times do
limiter.async do |task|
task.sleep 1
end
end
end
The above limiter runs two tasks concurrently at any point in time. After first
two tasks are done it waits for the 2-second window to finish before running
the next two tasks.
The total duration of the above example is 3s.
Differences between fixed and sliding window limiter
Notes
lock: false
onAsync:
:Continuous
Example
require "async"
require "async/limiter/window/continuous"
Async do
limiter = Async::Limiter::Window::Continuous.new(2, window: 1)
4.times do
limiter.async do |task|
task.sleep 0.1
end
end
end
The above limiter runs one task when it starts. It then waits 500ms (half the
window duration) before running the second task in the first window.
500ms later (1s after start) new window begins and it runs the third task,
waits another 500ms and runs the last task.
The total duration of the above example is 1.6s.
Notes
lock: false
onwindow.to_f / limit
time after the previous task started.Async:
:Unlimited
Always runs tasks immediately, without limits.
This limiter is not intended for production use.
Example
require "async"
require "async/limiter/unlimited"
Async do
limiter = Async::Limiter::Unlimited.new
100.times do
limiter.async do |task|
task.sleep 1
end
end
end
All 100 tasks in the example above start immediately and run at the same time.
The total duration of the above example is 1s.
limit
All limiters except Async:
have :Unlimited
#limit=
. It allows
live updating of the limit
. Just set a new value and limiter will do the
right thing while it actively runs existing tasks.
Decimal values
Setting limit
to decimal values is allowed. Examples:
Since decimal value for a limit doesn’t make sense (how do you run half a task
per second?), decimal limit is internally always converted to a whole number
and window is adjusted appriately. So half a task per second actually runs as
one task in two seconds.
window
All window limiters have #window=
. It allows live updating of the window
.
Just set a new value and limiter will do the right thing while it actively runs
existing tasks.
This project is maintained actively, but on a slow schedule. Due to author’s
current life obligations it is likely:
If you want to help you can submit a small (e.g. 5 lines of code) and focused
PR. PRs containing big changes or new, unasked for features require a lot
of time to review and I often don’t get to those.
Inspiration and parts of the code taken from
Async::Semaphore.
You have full permission to fork, copy, and do whatever you want with this code.