-
-
Save wycats/2420126 to your computer and use it in GitHub Desktop.
class TicketsController < ApplicationController | |
def show | |
tickets = params[:tickets].split(",") | |
ticket_data = tickets.map do |ticket| | |
parallel { Faraday.get("http://tickets.local/#{ticket}") } | |
end | |
render json: { tickets: ticket_data.map(&:result) } | |
end | |
end |
require "future" | |
module ActionController | |
module ParallelIO | |
def parallel(&block) | |
Future.new(&block) | |
end | |
end | |
end | |
ActiveSupport.on_load(:action_controller) do | |
include ActionController::ParallelIO | |
end |
require "thread" | |
class Future | |
attr_reader :exception, :cancelled | |
def initialize(&block) | |
@thread = Thread.new(&block) | |
@thread.abort_on_exception = false | |
@exception = nil | |
@cancelled = false | |
end | |
def running? | |
@thread.alive? | |
end | |
def cancelled? | |
@cancelled | |
end | |
def done? | |
[email protected]? | |
end | |
def cancel | |
@cancelled = true | |
@thread.kill | |
end | |
def result(limit=nil) | |
value(limit) | |
rescue Exception => e | |
@exception = e | |
nil | |
end | |
def exception(limit=nil) | |
result(limit) | |
@exception | |
end | |
private | |
def value(limit) | |
if @thread.join(limit) | |
@thread.value | |
else | |
nil | |
end | |
end | |
end | |
q = Queue.new | |
require "uri" | |
require "net/http" | |
futures = {} | |
["http://www.google.com", "http://www.heroku.com", "http://www.github.com"].each do |url| | |
futures[url] = Future.new { Net::HTTP.get(URI(url)) } | |
end | |
futures["http://www.github.com"].cancel | |
puts "heroku.com:" | |
p futures["http://www.heroku.com"].cancelled? | |
puts futures["http://www.heroku.com"].result | |
puts futures["http://www.heroku.com"].exception | |
puts | |
puts "google.com:" | |
p futures["http://www.google.com"].cancelled? | |
puts futures["http://www.google.com"].result | |
puts futures["http://www.google.com"].exception | |
puts "github.com:" | |
p futures["http://www.github.com"].cancelled? | |
puts futures["http://www.github.com"].result | |
puts futures["http://www.github.com"].exception |
Concurrent? Yes. Parallel? Not really. Not on MRI at least. Or am I confused about GIL?
In case I am not confused, then possibly fibers would make a better job than threads?
@wycats: Thanks for the gist. May I suggest you provide a quick explanation of the upsides and benefits of such a technique for less technical users? i.e. explain what that code achieves and how exactly one would leverage such a feature in one's code?
@artemave JRuby and Rubinius both support parallel multithreading because they have fine-grained locking models instead of a GIL. So this is extremely relevant to those platforms.
Even on MRI/YARV, you can do parallel blocking I/O, and C extensions can explicitly release the GIL for computationally intensive activities as well.
oh, it is so cool!