Skip to content

v1.1.6

Latest

Choose a tag to compare

@bdurand bdurand released this 14 Aug 23:12
Immutable release. Only release title and notes can be modified.
f51fa20

Fixed

  • Queries on relations with conditions that cannot be represented in the cache key (SQL string conditions, ranges, not, or, joins, group, having, from, offset, locking, or non-hash find_by arguments) now bypass the cache instead of silently ignoring those conditions and returning or caching the wrong record.
  • create_with values are no longer included in cache keys, so queries using create_with can now be cached correctly.
  • Queries inside an open transaction now bypass the cache so that uncommitted data can never be cached. Previously a rolled back transaction could permanently poison the cache with data that was never committed. Transactions created with joinable: false (such as Rails transactional test fixtures) still use the cache.
  • Cache invalidation now runs even when caching is disabled. Previously records changed inside a disable block (or while caching was disabled globally) left stale entries behind for when caching was re-enabled.
  • Cache key values are now cast through the attribute type, so equivalent values (e.g. :one and "one", or "5" and 5) produce the same cache key. Previously such entries could be written under keys that the invalidation callbacks could never delete. This also fixes cache keys for false attribute values, which were previously indistinguishable from nil.
  • load_cache no longer raises an error when caching is disabled and now honors where conditions on cache_by configurations instead of caching records that do not match them. It also refreshes existing cache entries instead of skipping them.
  • A cache_by configuration whose where clause does not match a query no longer prevents later configurations from matching, and no longer mutates the query attributes while matching.
  • Calling cache_by in a subclass no longer mutates the superclass's cache configuration.
  • Models that include SupportTableCache without calling cache_by no longer raise an error on find_by.
  • Calling cache_belongs_to more than once for the same association no longer causes infinite recursion when reading the association.
  • SupportTableCache::MemoryCache now synchronizes all access to the underlying hash (previously reads, deletes, and clears were unsynchronized), purges expired entries, and no longer serializes values twice on a cache miss. A fetch that races with a concurrent delete or clear no longer stores its stale value back in the cache.
  • The where clause on a cache_by configuration is now matched against query attributes using values cast through the attribute type, so equivalent values (e.g. 1 and "1") match the same way they do when building cache keys.
  • A find_by that specifies a different value for an attribute than the relation it is chained onto (i.e. where(name: "Two").find_by(name: "One")) now bypasses the cache. Previously the find_by value replaced the relation's value in the cache key so a cached record excluded by the relation could be returned.
  • fetch_by and fetch_by! now raise an ArgumentError if a query cannot be matched to a cache key because it does not satisfy the where condition on a cache_by configuration or because it conflicts with the relation it is chained onto. Previously these queries silently fell back to the database, which defeats the purpose of the safety check. Queries on a model with a default scope matching a cache_by where condition no longer raise an error.
  • SupportTableCache::FiberLocals now stores state in the fiber's native local storage so that state cannot leak from fibers that are garbage collected while suspended inside a block.

Full Changelog: v1.1.5...v1.1.6