All Articles

Rails preserves entry TTL when incrementing or decrementing an integer value.

Caching solutions like MemCache and Redis always preserve expiration, while altering a value to avoid any discrepancies caused by it. Previously, while incrementing or decrementing an integer value in MemoryStore, Rails used to reset the expires_in associated with the entry, for eg-

Before

Let’s say, we are storing certain number of likes on a product as a like_counter in MemoryStore for 10 seconds. Here, if we increment or decrement the counter, it is used to reset the TTL.

irb(main):004:0> cache = ActiveSupport::Cache.lookup_store(:memory_store)
irb(main):004:0> cache.write("like_counter", 1, raw: true, expires_in: 10.seconds)
irb(main):004:0> sleep(2.seconds)
irb(main):004:0> cache.increment("like_counter")
irb(main):004:0> sleep(8.seconds)
irb(main):004:0> cache.read("like_counter")
irb(main):004:0> 2

As we can see after 10 seconds, like_counter should have been deleted from the store, however, it still shows the incremented value because cache.increment("like_counter") set the timer again to 10 seconds.

After

Now, Rails preserves expires_in while incrementing or decrementing an integer value in MemoryStore.

irb(main):004:0> cache = ActiveSupport::Cache.lookup_store(:memory_store)
irb(main):004:0> cache.write("like_counter", 1, raw: true, expires_in: 10.seconds)
irb(main):004:0> sleep(2.seconds)
irb(main):004:0> cache.increment("like_counter")
irb(main):004:0> sleep(8.seconds)
irb(main):004:0> cache.read("like_counter")
irb(main):004:0> nil

As it can be seen, though we had incremented the counter, the key got expired after 10 seconds and returned nil

Check out the PR for more details.