API
gs
Request handlers
Compressors
Publisher
Output
Producers
Processors
Collector
A pipeline, indeed!
A concurrent paradigm where
Processes communicate
by passing messages
over channels
A concurrent paradigm where
Processes Fibers communicate
by passing messages
over Channels
A concurrent paradigm where
Processes Fibers communicate
by passing messages
over channels
Fibers
Lightweight
Cooperative
Unit of execution
A concurrent paradigm where
Processes Fibers communicate
by passing messages
over Channels
Channels
blocking #send and #receive
similar to queues
Regulate data exchange between fibers
Fibers
Channel
Message
spawn do
# your concurrent task!
endTo start a Fiber we
ch = Channel(Job).newCreating a Channel
Sending & receiving
ch.send(Msg.new(uuid))msg = ch.receivech = Channel(Job).new
msg = Msg.new(uuid)
ch.send msg
puts ch.receivech = Channel(Job).new
msg = Msg.new(uuid)
ch.send msg
puts ch.receivech = Channel(Job).new
msg = Msg.new(uuid)
ch.send msg
puts ch.receivech = Channel(Job).new
msg = Msg.new(uuid)
ch.send msg
puts ch.receivech = Channel(Job).new
msg = Msg.new(uuid)
ch.send msg
puts ch.receiveX
ch = Channel(Job).new
msg = Msg.new(uuid)
ch.send msg
puts ch.receiveX
When a Fiber blocks, it yields control to another Fiber.
Fiber.yieldsleep 2HTTP.get(url)ch.receivech.send objfiber A
Thread
Scheduler
Thread
Scheduler
fiber A
fiber B
Scheduler
Thread
fiber A
fiber B
spawn(name: "fiber A") do
spawn(name: "fiber Z") do
# do something
end
msg = ch.receive
endfiber Z
Scheduler
Thread
fiber A
fiber B
spawn(name: "fiber A") do
spawn(name: "fiber Z") do
# do something
end
msg = ch.receive
endfiber Z
Scheduler
Thread
fiber A
Thread
fiber B
spawn(name: "fiber A") do
spawn(name: "fiber Z") do
# do something
end
msg = ch.receive
endfiber Z
Scheduler
Thread
fiber A
Thread
fiber B
fiber Z
Scheduler
Thread
Thread
fiber B
fiber A
fiber Z
Scheduler
Thread
fiber A
Thread
fiber B
fiber C
fiber Z
Scheduler
Thread
Thread
fiber C
fiber A
fiber B
spawn(name: "fiber B") do
Fiber.yield
endfiber Z
Scheduler
Thread
Thread
fiber C
fiber A
fiber B
fiber Z
Scheduler
Thread
Thread
fiber C
fiber A
fiber B
fiber Z
ch = Channel(Job).new
msg = Msg.new(uuid)
spawn(name: "processor") do
puts ch.receive
end
ch.send msg
ch = Channel(Job).new
msg = Msg.new(uuid)
spawn(name: "processor") do
puts ch.receive
end
ch.send msg
ch = Channel(Job).new
msg = Msg.new(uuid)
spawn(name: "processor") do
puts ch.receive
end
ch.send msg
ch = Channel(Job).new
msg = Msg.new(uuid)
spawn(name: "processor") do
puts ch.receive
end
ch.send msg
ch = Channel(Job).new
msg = Msg.new(uuid)
spawn(name: "processor") do
puts ch.receive
end
ch.send msg
X
ch = Channel(Job).new
msg = Msg.new(uuid)
spawn(name: "processor") do
puts ch.receive
end
ch.send msg
X
ch = Channel(Job).new
msg = Msg.new(uuid)
spawn(name: "processor") do
puts ch.receive
end
ch.send msg
X
ch = Channel(Job).new
msg = Msg.new(uuid)
spawn(name: "processor") do
puts ch.receive
end
ch.send msg
ch = Channel(Job).new
msg = Msg.new(uuid)
spawn(name: "processor") do
puts ch.receive
end
ch.send msg
Termination
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
X
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
X
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
X
X
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
X
X
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
X
X
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
X
X
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
X
X
X
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
X
X
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
X
X
X
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
X
X
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
X
X
X
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
X
X
ch = Channel(Job).new
2.times.each { |i|
spawn(name: "processor_#{i}") do
loop do
puts "#{Fiber.current.name}: #{ch.receive}"
end
end
}
loop do
ch.send Msg.new(UUID.random)
sleep 0.5
end
X
X
To share state we communicate via channels
Job_id_stream = Channel(Int32).new
spawn(name: "job_id_generator") do
i = 0
loop do
Job_id_stream.send i
i += 1
end
end
def handle_request(request)
job_id = Job_id_stream.receive
# ...
endTo share state we communicate via channels
Job_id_stream = Channel(Int32).new
spawn(name: "job_id_generator") do
i = 0
loop do
Job_id_stream.send i
i += 1
end
end
def handle_request(request)
job_id = Job_id_stream.receive
# ...
endTo share state we communicate via channels
Job_id_stream = Channel(Int32).new
spawn(name: "job_id_generator") do
i = 0
loop do
Job_id_stream.send i
i += 1
end
end
def handle_request(request)
job_id = Job_id_stream.receive
# ...
endTo share state we communicate via channels
Job_id_stream = Channel(Int32).new
spawn(name: "job_id_generator") do
i = 0
loop do
Job_id_stream.send i
i += 1
end
end
def handle_request(request)
job_id = Job_id_stream.receive
# ...
endJob_stream = Channel(Job).new
def handle_request(request)
params = extract_params(request)
job_id = Job_id_stream.receive
persist(job_id, params.file)
job = Job.new(job_id, params.options)
Job_stream.send(job)
end
WORKERS.each {
spawn do
loop do
process(Job_stream.receive)
end
end
}Job_stream = Channel(Job).new
def handle_request(request)
params = extract_params(request)
job_id = Job_id_stream.receive
persist(job_id, params.file)
job = Job.new(job_id, params.options)
Job_stream.send(job)
end
WORKERS.each {
spawn do
loop do
process(Job_stream.receive)
end
end
}Job_stream = Channel(Job).new
def handle_request(request)
params = extract_params(request)
job_id = Job_id_stream.receive
persist(job_id, params.file)
job = Job.new(job_id, params.options)
Job_stream.send(job)
end
WORKERS.each {
spawn do
loop do
process(Job_stream.receive)
end
end
}Fibers
Channels
Success!
{
name: lorenzo.barasti,
live_codes_on: twitch.com/lbarasti,
blogs_at: lbarasti.com,
tweets_as: @lbarasti
}
Thanks for listening!