Async
Async is a gem, not a language feature.
bundle add async
Async and wait
The top level Async block is needed to create a reactor context to
do the scheduing, otherwise the first puts won't get executed utill
the task is finished.
require 'async'
Async do
task = Async do
sleep 1
rand
end
puts "wait for 1 second"
puts task.wait
end
Concurrency
Async do
tasks = (1..5).map do |x|
Async do
sleep 1
x
end
end
puts tasks.map(&:wait)
end
Limiting Concurrency Level
require 'async'
require 'async/semaphore'
Async do
semaphore = Async::Semaphore.new(2)
(1..5).each do |x|
semaphore.async do
puts "#{x} started"
sleep 1
puts " #{x} finished"
end
end
end
Waiting for tasks
Barrier can be used to wait for a group of tasks, but you can just
simplely do tasks.each(&:wait).
Waiter can be used to wait for a specific number of tasks from all
tasks, kind of like Promise.race in js or select in go, but more
flexible.
Barrier and Waiter can be used together.
require 'async'
require 'async/waiter'
require 'async/barrier'
barrier = Async::Barrier.new
waiter = Async::Waiter.new(parent: barrier)
Async do
[3, 2, 1].each do |x|
waiter.async do
sleep x
x
end
end
puts waiter.wait(2).inspect
# stop the remaining jobs
barrier.stop
end
this should puts
[1, 2]
Timeouts
require 'async'
Async do |task|
task.with_timeout(0.5) do
sleep rand
rescue Async::TimeoutError
puts "timeout!"
end
end