Skip to content

Instantly share code, notes, and snippets.

@wycats
Created April 19, 2012 10:22
Show Gist options
  • Save wycats/2420126 to your computer and use it in GitHub Desktop.
Save wycats/2420126 to your computer and use it in GitHub Desktop.
Example of using a simple future library for parallel HTTP requests
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
@artemave
Copy link

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?

@Veejay
Copy link

Veejay commented Apr 19, 2012

@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?

@tarcieri
Copy link

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment