Skip to content

Instantly share code, notes, and snippets.

@ismasan
Created August 16, 2013 17:46
Show Gist options
  • Save ismasan/6251948 to your computer and use it in GitHub Desktop.
Save ismasan/6251948 to your computer and use it in GitHub Desktop.
Use futures to fetch all products in a page concurrently. With futures: ~5 seconds Without: ~ 32 seconds
require "open-uri"
require 'json'
def json(url)
JSON.parse(open(url, 'Authorization' => 'Bearer API_TOKEN').read)
end
class Future < BasicObject
def initialize(callable)
@thread ||= ::Thread.new { callable.call }
end
def value
@thread.value
end
def inspect
if @thread.alive?
"#<Future running>"
else
value.inspect
end
end
def method_missing(method, *args)
value.send(method, *args)
end
def respond_to_missing?(method, include_private = false)
value.respond_to?(method, include_private)
end
end
module Kernel
def future(&block)
Future.new(block)
end
end
class Resource
def initialize(url)
@url = url
end
def links
document['items'].map {|pr| pr['links']['self']['href']}
end
def title
document['properties']['title']
end
def description
document['properties']['description']
end
def get
document
self
end
private
def document
@document ||=json(@url)
end
end
class Index
def initialize(url)
@resource = Resource.new(url)
end
def urls
@resource.links
end
end
class Crawler
def initialize(index)
@index = index
end
def crawl
resources.each do |page|
Outputter.new(page).output
end
end
private
def resources
@index.urls.map do |url|
future { Resource.new(url).get }
# Resource.new(url).get
end
end
end
require "highline"
class Outputter
OUTPUT_WIDTH = 79
def initialize(page)
@page = page
end
def output
highline.say("-" * OUTPUT_WIDTH)
highline.say(@page.title)
highline.say("-" * OUTPUT_WIDTH)
highline.say("\n\n")
end
private
def highline
@highline ||= HighLine.new($stdin, $stdout, OUTPUT_WIDTH)
end
end
Crawler.new(Index.new("https://api.bootic.net/v1/products.json")).crawl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment