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!
end
To start a Fiber we
ch = Channel(Job).new
Creating a Channel
Sending & receiving
ch.send(Msg.new(uuid))
msg = ch.receive
ch = Channel(Job).new
msg = Msg.new(uuid)
ch.send msg
puts ch.receive
ch = Channel(Job).new
msg = Msg.new(uuid)
ch.send msg
puts ch.receive
ch = Channel(Job).new
msg = Msg.new(uuid)
ch.send msg
puts ch.receive
ch = Channel(Job).new
msg = Msg.new(uuid)
ch.send msg
puts ch.receive
ch = Channel(Job).new
msg = Msg.new(uuid)
ch.send msg
puts ch.receive
X
ch = Channel(Job).new
msg = Msg.new(uuid)
ch.send msg
puts ch.receive
X
When a Fiber blocks, it yields control to another Fiber.
Fiber.yield
sleep 2
HTTP.get(url)
ch.receive
ch.send obj
fiber 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
end
fiber Z
Scheduler
Thread
fiber A
fiber B
spawn(name: "fiber A") do
spawn(name: "fiber Z") do
# do something
end
msg = ch.receive
end
fiber Z
Scheduler
Thread
fiber A
Thread
fiber B
spawn(name: "fiber A") do
spawn(name: "fiber Z") do
# do something
end
msg = ch.receive
end
fiber 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
end
fiber 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
# ...
end
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
# ...
end
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
# ...
end
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
# ...
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
}
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!