класс ActiveSupport::Cache::Store
Абстрактный класс хранилища кэша. Существует несколько реализаций хранилищ кэша, каждая со своими дополнительными функциями. См. классы в модуле ActiveSupport::Cache, например, ActiveSupport::Cache::MemCacheStore. MemCacheStore в настоящее время является наиболее популярным хранилищем кэша для крупных сайтов в производстве.
Некоторые реализации могут не поддерживать все методы, кроме основных методов кэша fetch, write, read, exist?, и delete.
ActiveSupport::Cache::Store может хранить любые сериализуемые объекты Ruby.
cache = ActiveSupport::Cache::MemoryStore.new
cache.read('city') # => nil
cache.write('city', "Duckburgh")
cache.read('city') # => "Duckburgh"
Ключи всегда переводятся в строки и регистрозависимы. Когда объект указан в качестве ключа и имеет определённый метод cache_key, этот метод будет вызван для определения ключа. В противном случае будет вызван метод to_param. Массивы и хэши также могут быть использованы в качестве ключей. Элементы будут разделены слешами, а элементы в хэше будут отсортированы по ключу, чтобы обеспечить согласованность.
cache.read('city') == cache.read(:city) # => true
Значения Nil могут быть кэшированы.
Если ваш кэш находится на общей инфраструктуре, вы можете определить пространство имен для ваших записей кэша. Если пространство имен определено, оно будет добавляться в префикс к каждому ключу. Пространство имен может быть статическим значением или объектом Proc. Если это Proc, он будет вызываться при оценке каждого ключа, чтобы вы могли использовать логику приложения для удаления ключей.
cache.namespace = -> { @last_mod_time } # Set the namespace to a variable
@last_mod_time = Time.now # Invalidate the entire cache by changing namespace
Данные кэша размером более 1 КБ сжимаются по умолчанию. Чтобы отключить сжатие, передайте compress: false в инициализатор или в отдельные вызовы методов fetch или write. Порог сжатия 1 КБ настраивается с помощью параметра :compress_threshold, указанного в байтах.
Атрибуты
Общедоступные методы класса
# File activesupport/lib/active_support/cache.rb, line 183
def initialize(options = nil)
@options = options ? options.dup : {}
end Создаёт новый кэш. Параметры будут переданы в любые вызовы метода записи, за исключением :namespace, который может быть использован для установки глобального пространства имен для кэша.
Общедоступные методы экземпляра
# File activesupport/lib/active_support/cache.rb, line 505
def cleanup(options = nil)
raise NotImplementedError.new("#{self.class.name} does not support cleanup")
end Очищает кэш, удаляя просроченные записи.
Параметры передаются в базовую реализацию кэша.
Не все реализации могут поддерживать этот метод.
# File activesupport/lib/active_support/cache.rb, line 515
def clear(options = nil)
raise NotImplementedError.new("#{self.class.name} does not support clear")
end Очищает весь кэш. Будьте осторожны с этим методом, так как он может повлиять на другие процессы, если используется общий кэш.
Хэш параметров передается в базовую реализацию кэша.
Не все реализации могут поддерживать этот метод.
# File activesupport/lib/active_support/cache.rb, line 496
def decrement(name, amount = 1, options = nil)
raise NotImplementedError.new("#{self.class.name} does not support decrement")
end Уменьшает целое значение в кэше.
Параметры передаются в базовую реализацию кэша.
Не все реализации могут поддерживать этот метод.
# File activesupport/lib/active_support/cache.rb, line 453
def delete(name, options = nil)
options = merged_options(options)
instrument(:delete, name) do
delete_entry(normalize_key(name, options), options)
end
end Удаляет запись из кэша. Возвращает true если запись была удалена.
Параметры передаются в базовую реализацию кэша.
# File activesupport/lib/active_support/cache.rb, line 478
def delete_matched(matcher, options = nil)
raise NotImplementedError.new("#{self.class.name} does not support delete_matched")
end Удаляет все записи с ключами, соответствующими шаблону.
Параметры передаются в базовую реализацию кэша.
Не все реализации могут поддерживать этот метод.
# File activesupport/lib/active_support/cache.rb, line 464
def exist?(name, options = nil)
options = merged_options(options)
instrument(:exist?, name) do
entry = read_entry(normalize_key(name, options), options)
(entry && !entry.expired? && !entry.mismatched?(normalize_version(name, options))) || false
end
end Возвращает true если кэш содержит запись для данного ключа.
Параметры передаются в базовую реализацию кэша.
# File activesupport/lib/active_support/cache.rb, line 306
def fetch(name, options = nil)
if block_given?
options = merged_options(options)
key = normalize_key(name, options)
entry = nil
instrument(:read, name, options) do |payload|
cached_entry = read_entry(key, options) unless options[:force]
entry = handle_expired_entry(cached_entry, key, options)
entry = nil if entry && entry.mismatched?(normalize_version(name, options))
payload[:super_operation] = :fetch if payload
payload[:hit] = !!entry if payload
end
if entry
get_entry_value(entry, name, options)
else
save_block_result_to_cache(name, options) { |_name| yield _name }
end
elsif options && options[:force]
raise ArgumentError, "Missing block: Calling `Cache#fetch` with `force: true` requires a block."
else
read(name, options)
end
end Извлекает данные из кэша, используя заданный ключ. Если в кэше есть данные с заданным ключом, то эти данные возвращаются.
Если таких данных в кэше нет (промах кэша), то возвращается nil. Однако, если был передан блок, этот блок будет передан ключ и выполнен в случае промаха кэша. Возвращаемое значение блока будет записано в кэш по данному ключу кэша, и это возвращаемое значение будет возвращено.
cache.write('today', 'Monday')
cache.fetch('today') # => "Monday"
cache.fetch('city') # => nil
cache.fetch('city') do
'Duckburgh'
end
cache.fetch('city') # => "Duckburgh"
Вы также можете указать дополнительные параметры через аргумент options. Установка force: true принудительно создает «промах» кэша, то есть мы рассматриваем значение кэша как отсутствующее, даже если оно присутствует. Передача блока обязательна, когда force имеет значение true, так как это всегда приводит к записи в кэш.
cache.write('today', 'Monday')
cache.fetch('today', force: true) { 'Tuesday' } # => 'Tuesday'
cache.fetch('today', force: true) # => ArgumentError
Параметр :force полезен, когда вы вызываете другой метод, чтобы спросить, нужно ли принудительно записать в кэш. В противном случае понятнее просто вызвать Cache#write.
Установка compress: false отключает сжатие записи кэша.
Установка :expires_in задаст время истечения срока действия кэша. Все кэши поддерживают автоматическое истечение срока действия содержимого после определенного количества секунд. Это значение может быть указано как параметр конструктора (в этом случае все записи будут затронуты), или может быть предоставлено методам fetch или write для воздействия только на одну запись.
cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes) cache.write(key, value, expires_in: 1.minute) # Set a lower value for one entry
Установка :version проверяет, что кэш, хранящийся по ключу name, имеет ту же версию. При несовпадении возвращается значение nil, несмотря на содержимое. Эта функция используется для поддержки повторно используемых ключей кэша.
Установка :race_condition_ttl очень полезна в ситуациях, когда запись в кэше используется очень часто и находится под большой нагрузкой. Если кэш истекает, и из-за высокой нагрузки несколько разных процессов попытаются прочитать данные напрямую, а затем все они попытаются записать в кэш. Для предотвращения этой ситуации первый процесс, обнаруживший просроченную запись в кэше, увеличит время истечения срока действия кэша на значение, заданное в :race_condition_ttl. Да, этот процесс продлевает время жизни устаревшего значения на несколько секунд. Из-за продленного срока жизни предыдущего кэша другие процессы продолжат использовать слегка устаревшие данные чуть дольше. Тем временем этот первый процесс продолжит запись нового значения в кэш. После этого все процессы начнут получать новое значение. Важно, чтобы :race_condition_ttl было небольшим.
Если процесс, возобновляющий запись, завершится ошибкой, запись будет перегенерирована после указанного числа секунд. Также обратите внимание, что срок жизни устаревшего кэша продлевается только в случае недавнего истечения срока действия. В противном случае генерируется новое значение, и :race_condition_ttl никакой роли не играет.
# Set all values to expire after one minute.
cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 1.minute)
cache.write('foo', 'original value')
val_1 = nil
val_2 = nil
sleep 60
Thread.new do
val_1 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
sleep 1
'new value 1'
end
end
Thread.new do
val_2 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
'new value 2'
end
end
cache.fetch('foo') # => "original value"
sleep 10 # First thread extended the life of cache by another 10 seconds
cache.fetch('foo') # => "new value 1"
val_1 # => "new value 1"
val_2 # => "original value"
Другие параметры будут обработаны конкретной реализацией хранилища кэша. Внутренне, fetch вызывает read_entry, а при промахе кэша вызывает write_entry. options будет передан в вызовы read и write.
Например, метод write MemCacheStore поддерживает параметр :raw, который сообщает серверу memcached о том, что все значения хранятся как строки. Мы можем использовать этот параметр и с fetch:
cache = ActiveSupport::Cache::MemCacheStore.new
cache.fetch("foo", force: true, raw: true) do
:bar
end
cache.fetch('foo') # => "bar"
# File activesupport/lib/active_support/cache.rb, line 416
def fetch_multi(*names)
raise ArgumentError, "Missing block: `Cache#fetch_multi` requires a block." unless block_given?
options = names.extract_options!
options = merged_options(options)
instrument :read_multi, names, options do |payload|
read_multi_entries(names, options).tap do |results|
payload[:hits] = results.keys
payload[:super_operation] = :fetch_multi
writes = {}
(names - results.keys).each do |name|
results[name] = writes[name] = yield(name)
end
write_multi writes, options
end
end
end Извлекает данные из кэша, используя заданные ключи. Если в кэше есть данные с заданными ключами, то эти данные возвращаются. В противном случае вызывается переданный блок для каждого ключа, для которого данных нет, а результат записывается в кэш и возвращается. Таким образом, вам нужно передать блок, который возвращает данные для записи в кэш. Если вы не хотите записывать в кэш, когда кэш не найден, используйте read_multi.
Параметры передаются в базовую реализацию кэша.
Возвращает хэш с данными для каждого из имен. Например:
cache.write("bim", "bam")
cache.fetch_multi("bim", "unknown_key") do |key|
"Fallback value for key: #{key}"
end
# => { "bim" => "bam",
# "unknown_key" => "Fallback value for key: unknown_key" }
# File activesupport/lib/active_support/cache.rb, line 487
def increment(name, amount = 1, options = nil)
raise NotImplementedError.new("#{self.class.name} does not support increment")
end Увеличивает целое значение в кэше.
Параметры передаются в базовую реализацию кэша.
Не все реализации могут поддерживать этот метод.
# File activesupport/lib/active_support/cache.rb, line 194 def mute previous_silence, @silence = defined?(@silence) && @silence, true yield ensure @silence = previous_silence end
Отключает регистратор внутри блока.
# File activesupport/lib/active_support/cache.rb, line 340
def read(name, options = nil)
options = merged_options(options)
key = normalize_key(name, options)
version = normalize_version(name, options)
instrument(:read, name, options) do |payload|
entry = read_entry(key, options)
if entry
if entry.expired?
delete_entry(key, options)
payload[:hit] = false if payload
nil
elsif entry.mismatched?(version)
payload[:hit] = false if payload
nil
else
payload[:hit] = true if payload
entry.value
end
else
payload[:hit] = false if payload
nil
end
end
end Читает данные из кэша, используя заданный ключ. Если в кэше есть данные с заданным ключом, то эти данные возвращаются. В противном случае возвращается nil.
Обратите внимание, если данные были записаны с параметрами :expires_in<tt> or
<tt>:version, оба этих условия применяются перед возвратом данных.
Параметры передаются в базовую реализацию кэша.
# File activesupport/lib/active_support/cache.rb, line 373
def read_multi(*names)
options = names.extract_options!
options = merged_options(options)
instrument :read_multi, names, options do |payload|
read_multi_entries(names, options).tap do |results|
payload[:hits] = results.keys
end
end
end Читает несколько значений одновременно из кэша. Параметры могут быть переданы в последнем аргументе.
Некоторые реализации кэша могут оптимизировать этот метод.
Возвращает хэш, сопоставляющий предоставленные имена найденным значениям.
# File activesupport/lib/active_support/cache.rb, line 188 def silence! @silence = true self end
Отключает регистратор.
# File activesupport/lib/active_support/cache.rb, line 441
def write(name, value, options = nil)
options = merged_options(options)
instrument(:write, name, options) do
entry = Entry.new(value, options.merge(version: normalize_version(name, options)))
write_entry(normalize_key(name, options), entry, options)
end
end Записывает значение в кэш с указанным ключом.
Параметры передаются в базовую реализацию кэша.
# File activesupport/lib/active_support/cache.rb, line 385
def write_multi(hash, options = nil)
options = merged_options(options)
instrument :write_multi, hash, options do |payload|
entries = hash.each_with_object({}) do |(name, value), memo|
memo[normalize_key(name, options)] = Entry.new(value, options.merge(version: normalize_version(name, options)))
end
write_multi_entries entries, options
end
end Кэш API хранения для записи нескольких значений сразу.
Приватные методы экземпляра
# File activesupport/lib/active_support/cache.rb, line 524
def key_matcher(pattern, options) # :doc:
prefix = options[:namespace].is_a?(Proc) ? options[:namespace].call : options[:namespace]
if prefix
source = pattern.source
if source.start_with?("^")
source = source[1, source.length]
else
source = ".*#{source[0, source.length]}"
end
Regexp.new("^#{Regexp.escape(prefix)}:#{source}", pattern.options)
else
pattern
end
end Добавляет пространство имён, определённое в опциях, к шаблону, предназначенному для сопоставления ключей. Реализации, поддерживающие #delete_matched, должны вызывать этот метод для преобразования шаблона, сопоставляющего имена, в шаблон, сопоставляющий именованные ключи.
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.