Created
June 17, 2014 20:05
-
-
Save chingor13/493993e49bfb47056006 to your computer and use it in GitHub Desktop.
Bulk fetching
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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