artsy/garner — pull request #31 by fancyremarker (2013-06-14 04:11:16+00:00)
Title: A robust, hopefully production-ready caching implementation

to: @dblock
cc: @joeyAghion

Sorry for the big PR. I promise the next one will be more concise. The big change here was replacing the `CacheKey` strategy with a more robust `SafeCacheKey` strategy (better name suggestions welcome :wink:) which provides the same (or better) performance than Garner 0.3.3. The `CacheKey` strategy was OK — in fact, it fully mirrored the caching performance of Rails 4 — but it suffered from two critical flaws:

* The timestamp in default cache keys only has second precision. (Can you believe this?) In other words, if a document is cache-bound and then written to within a single second, the cache result will **always** be stale. This pull request adds nanosecond precision when using the `SafeCacheKey` strategy.
* Mongoid (and ActiveModel) classes don't have `cache_key` defined. So you can't bind to a class. This pull request solves that by proxying `Model.cache_key` to `Model.latest.cache_key`.

Some more minor, or structural changes:

* Separated callback invalidations from explicit invalidations via `invalidate_garner_caches`. Motivation: In the specific case of the `Touch` invalidation strategy, it's redundant and even possibly harmful for us to call `touch` on documents during Mongoid callbacks.
* Added a spec for the potential race condition brought up by @dblock in #28. Because `SafeCacheKey` always uses the actual database state as truth, it probably wasn't an issue here, but could very well be an issue for other strategies, like the `IdentityMap` strategy I'm working on. So thanks again for bringing up the corner case.
* Rewrote all strategies as classes, not models, inheriting from respective `Base` classes. There's a minor need now (see `apply_on_callback?`), and conceivably a major need later, for inheritable behavior in strategy groups.
* Fixed Coveralls, and made it only run in CI.

Pending any changes you guys suggest, I think this is ready for production. *(Famous last words.)* Let's :shipit:!