Shopify/identity_cache — pull request #32 by hornairs (2013-05-01 19:06:14+00:00)
Title: Deep association batch prefetches

This makes this piece of code:

```ruby
Product.fetch_multi(1,2,3,4,5, {:includes => {:product_variants => :product_variant_adjustment}})
```

do 3 (three) (:three:) memcache `GET MULTI`s instead of 1 + N + N*M calls. Woo!

This is that arel stuff I was ranting about before. If we have to fetch big tree of associated objects, it would be best if no matter how many objects there were at each level of the tree we still only did one `fetch_multi` to hit memcache only once for all the data we need. To be as clear as possible, take a look at this tree of associated objects:

```

+-------+ +-------+ +-------+
|Product| |Product| |Product|
+-------+ +-------+ +-------+

+-------+ +-------+ +-------++-------+ +-------++-------++-------+
|Variant| |Variant| |Variant||Variant| |Variant||Variant||Variant|
+-------+ +-------+ +-------++-------+ +-------++-------++-------+

+---++---+ +---++---+ +---+ +---++---+ +---++---+ +---+ +---++---+
|PVA||PVA| |PVA||PVA| |PVA| |PVA||PVA| |PVA||PVA| |PVA| |PVA||PVA|
+---++---+ +---++---+ +---+ +---++---+ +---++---+ +---+ +---++---+
+---+ +---+ +---+ +---++---+ +---+ +---++---+
|PVA| |PVA| |PVA| |PVA||PVA| |PVA| |PVA||PVA|
+---+ +---+ +---+ +---++---+ +---+ +---++---+
+---+
|PVA|
+---+
```

Right now, if you `fetch_multi` the three products, and then later do `fetch_variants` on each one, each call to `fetch_variants` will reach out to memcached. If you also ever do `fetch_product_variant_adjustments` on the `ProductVariant` model, you generate a call each time. We have this situation in Shopify most often when doing serialization.

This change makes IDC (if you opt in) traverse the tree one level at a time, doing one `fetch_multi` per tree level. Looking at the tree above it will do one for the first three products, then grab the list of variant ids for *all* the products involved and do one efficient `fetch_multi` for all the variant_ids, and then associate the returned variants with the correct parent. If the top level call also asked for the adjustments, *all* the adjustment IDs will be gathered and one `fetch_multi` will be issued for them.

So yeah, I think we should merge this! I would really like some feedback from you guys on other stuff to test and how to refactor the insane method I wrote. It came out kind of hastily so any and all recommendations are welcome. I'm going to work on introducing this to the `AcceleratedJsonFinder` later today and prove that it covers the use case there.

@camilo @burke @boourns @jduff