Rails 5.2.1 changes Redis cache deletion and compression
Rails 5.2.1 replaces blocking pattern deletion with batched Redis scanning and fixes cache storage inflation. Existing inflated entries need separate cleanup because the patch does not rewrite stored data.
Deleting a group of cache keys can interfere with unrelated users of the cache server if the deletion monopolizes it. Rails 5.2.1 changes the Redis cache store's pattern-deletion implementation from an evaluated Lua operation to a batched scan-and-delete loop. It also corrects a separate compression problem that could substantially inflate cache storage.
The August 7 release announcement links the component changelogs for this maintenance release. The Active Support changelog identifies both cache changes and explicitly states that the compression patch does not repair existing data. Updating code and removing already problematic entries are therefore separate actions.
I find Ruby's collection APIs readable, but a short method call can represent substantial work against an external service. A pattern deletion is one such operation. The new implementation makes its work incremental while retaining the Rails cache-store interface.
Pattern deletion becomes a cursor loop
The 5.2.1 Redis cache store validates that its matcher is a string and constructs the namespaced Redis pattern. It initializes a cursor, calls SCAN with that pattern and a batch-size parameter, then deletes the returned keys when the batch is nonempty.
The loop continues until the cursor returns to zero. This changes one large server-side operation into a sequence of requests. The source comments describe the purpose as avoiding a blocking Redis operation while finding matching keys.
The method still has work proportional to what its iteration must examine and delete. Batching changes how that work reaches the server. It does not turn deleting a large family of keys into a constant amount of computation.
This is a practical distinction for a cache maintenance operation. An application can request the same logical deletion while the implementation gives the server opportunities between requests. The release changelog's nonblocking description concerns that change in execution pattern.
The matcher remains a Redis glob string. The method raises an argument error for an unsupported matcher representation. A framework abstraction can accept a familiar operation while still retaining the backend's specific pattern language.
Compression must justify its stored representation
The cache compression fix concerns the amount of stored data. The changelog says compression could massively inflate cache storage, even though compression is enabled by default. With the correction, the cache stops producing that problematic representation for new entries.
The 5.2.1 cache entry implementation shows the size comparison. It determines an uncompressed size according to the value's kind, serializes when needed and deflates the serialized data. It retains the compressed result only if its byte size is smaller than the uncompressed size.
The decision therefore depends on the actual candidate representation. Merely selecting compression does not establish that the result saves space. A value that fails to shrink should not automatically acquire a larger compressed representation.
The entry also records whether it retained compression. Reading the value inflates and unmarshals only when that flag is present. Storage format and read behavior are connected, which helps explain why changing the write logic does not automatically rewrite old entries.
The changelog asks users to flush the cache manually to remove existing problematic data. It does not claim that loading the new library repairs the stored objects. A running application can therefore have corrected write behavior while its cache still contains entries created by the earlier implementation.
Local cache reads have a separate correction
Active Support also fixes multi-value reads with local caching enabled. The changelog says the old behavior returned Cache::Entry objects in place of the raw values. The distinction is observable to an application expecting its cached result.
An entry contains bookkeeping alongside the value, including version and expiration information. Returning the wrapper leaks an internal representation into the caller's result. A correct read interface should provide the value that application code placed in the cache.
My preference is for these distinctions to remain inside the cache implementation. Application code using a cached value should not need a special case for whether a local cache layer happened to participate. The maintenance correction aligns the multi-read result with that expectation.
The patch addresses operations and existing state differently
These changes share the cache component but repair different contracts. Pattern deletion changes the way Redis work is scheduled. Compression changes which representation new entries retain. Multi-read fixes the object returned to the application when local caching is active.
The release announcement supplies checksums for the published component gems and links the full comparison from 5.2.0. Those identify the maintenance version, while the individual changelogs explain the relevant behavior. An upgrade can therefore be assessed against a specific cache workflow.
The remaining cleanup requirement comes from the compression changelog itself. Existing inflated entries survive the code update until removed or replaced. Rails 5.2.1 prevents the write behavior going forward, while the documented manual cache flush clears data already stored by the affected implementation.