mirror of https://github.com/rails/rails
Improve the example of ActiveSupport::Cache::Store#fetch
The original example has race condition issue that the output of the example isn't conistent, see https://github.com/rails/rails/issues/43588. The change improves the example by removing unnecessary thread and add detailed comments. In the new example, there will be race condition only if `ActiveSupport::Cache::MemoryStore` took longer than 0.1 second to extend expiry but that's unlikely to happen. Close #43588
This commit is contained in:
parent
554e71af0b
commit
a8bc63af54
|
@ -405,31 +405,47 @@ module ActiveSupport
|
||||||
# has elapsed.
|
# has elapsed.
|
||||||
#
|
#
|
||||||
# # Set all values to expire after one minute.
|
# # Set all values to expire after one minute.
|
||||||
# cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 1.minute)
|
# cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 1)
|
||||||
#
|
#
|
||||||
# cache.write('foo', 'original value')
|
# cache.write("foo", "original value")
|
||||||
# val_1 = nil
|
# val_1 = nil
|
||||||
# val_2 = nil
|
# val_2 = nil
|
||||||
# sleep 60
|
# p cache.read("foo") # => "original value"
|
||||||
#
|
#
|
||||||
# Thread.new do
|
# sleep 1 # wait until the cache expires
|
||||||
# val_1 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
|
#
|
||||||
|
# t1 = Thread.new do
|
||||||
|
# # fetch does the following:
|
||||||
|
# # 1. gets an recent expired entry
|
||||||
|
# # 2. extends the expiry by 2 seconds (race_condition_ttl)
|
||||||
|
# # 3. regenerates the new value
|
||||||
|
# val_1 = cache.fetch("foo", race_condition_ttl: 2) do
|
||||||
# sleep 1
|
# sleep 1
|
||||||
# 'new value 1'
|
# "new value 1"
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# Thread.new do
|
# # Wait until t1 extends the expiry of the entry
|
||||||
# val_2 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
|
# # but before generating the new value
|
||||||
# 'new value 2'
|
# sleep 0.1
|
||||||
# end
|
#
|
||||||
|
# val_2 = cache.fetch("foo", race_condition_ttl: 2) do
|
||||||
|
# # This block won't be executed because t1 extended the expiry
|
||||||
|
# "new value 2"
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# cache.fetch('foo') # => "original value"
|
# t1.join
|
||||||
# sleep 10 # First thread extended the life of cache by another 10 seconds
|
#
|
||||||
# cache.fetch('foo') # => "new value 1"
|
# p val_1 # => "new value 1"
|
||||||
# val_1 # => "new value 1"
|
# p val_2 # => "oritinal value"
|
||||||
# val_2 # => "original value"
|
# p cache.fetch("foo") # => "new value 1"
|
||||||
|
#
|
||||||
|
# # The entry requires 3 seconds to expire (expires_in + race_condition_ttl)
|
||||||
|
# # We have waited 2 seconds already (sleep(1) + t1.join) thus we need to wait 1
|
||||||
|
# # more second to see the entry expire.
|
||||||
|
# sleep 1
|
||||||
|
#
|
||||||
|
# p cache.fetch("foo") # => nil
|
||||||
#
|
#
|
||||||
# ==== Dynamic Options
|
# ==== Dynamic Options
|
||||||
#
|
#
|
||||||
|
|
Loading…
Reference in New Issue