Skip to content

Instantly share code, notes, and snippets.

@chingor13
Created June 17, 2014 20:05
Show Gist options
  • Save chingor13/493993e49bfb47056006 to your computer and use it in GitHub Desktop.
Save chingor13/493993e49bfb47056006 to your computer and use it in GitHub Desktop.
Bulk fetching
# This is an in-memory cache that can do bulk fetches (via find)
# You can queue up ids to fetch at a later time.
class BulkFetcher
def initialize
reset!
end
def queue(klass, ids)
@queue[klass] += Array(ids)
end
# returns objects by id
def fetch_all(klass, id_or_ids)
ids = Array(id_or_ids)
# fetch anything queued for this class
fetch_items(klass, @queue.delete(klass))
# look in the cache for hits
items, missing_ids = lookup_items(klass, ids)
# bulk fetch the missing ids
items += fetch_items(klass, missing_ids)
items.group_by(&:id)
end
# return a single object
def fetch(klass, id)
fetch_all(klass, id).fetch(id)
end
def reset!
@cache = {}
@queue = Hash.new { [] }
end
protected
def lookup_items(klass, ids)
missing = []
items = []
# find cache hits first
ids.each do |id|
if item = @cache.fetch(klass.name, {})[id]
items.push(item)
else
missing.push(id)
end
end
[items, missing]
end
def fetch_items(klass, ids)
return [] if ids.blank?
store_items(klass, klass.find(ids).to_a)
end
def store_items(klass, objects)
objects.each do |object|
@cache[klass.name] ||= {}
@cache[klass.name][object.id] = object
end
objects
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment