класс 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 . Массивы и хэши также могут использоваться в качестве ключей. Элементы будут разделены слешами, а элементы внутри Hash будут отсортированы по ключу, чтобы обеспечить согласованность.
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 203
def initialize(options = nil)
@options = options ? normalize_options(options) : {}
@options[:compress] = true unless @options.key?(:compress)
@options[:compress_threshold] = DEFAULT_COMPRESS_LIMIT unless @options.key?(:compress_threshold)
@coder = @options.delete(:coder) { default_coder } || NullCoder
@coder_supports_compression = @coder.respond_to?(:dump_compressed)
end Создаёт новый кэш. Параметры будут переданы любым методам записи, за исключением :namespace, который может быть использован для установки глобального пространства имён для кэша.
Публичные методы экземпляра
# File activesupport/lib/active_support/cache.rb, line 574
def cleanup(options = nil)
raise NotImplementedError.new("#{self.class.name} does not support cleanup")
end Очищает кэш, удаляя устаревшие записи.
Параметры передаются в реализацию базового кэша.
Некоторые реализации могут не поддерживать этот метод.
# File activesupport/lib/active_support/cache.rb, line 584
def clear(options = nil)
raise NotImplementedError.new("#{self.class.name} does not support clear")
end Очищает весь кэш. Будьте осторожны с этим методом, так как он может повлиять на другие процессы, если используется общий кэш.
Хэш параметров передается в реализацию базового кэша.
Некоторые реализации могут не поддерживать этот метод.
# File activesupport/lib/active_support/cache.rb, line 565
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 506
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 547
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 517
def delete_multi(names, options = nil)
options = merged_options(options)
names.map! { |key| normalize_key(key, options) }
instrument :delete_multi, names do
delete_multi_entries(names, **options)
end
end Удаляет несколько записей из кэша.
Параметры передаются в реализацию базового кэша.
# File activesupport/lib/active_support/cache.rb, line 529
def exist?(name, options = nil)
options = merged_options(options)
instrument(:exist?, name) do |payload|
entry = read_entry(normalize_key(name, options), **options, event: payload)
(entry && !entry.expired? && !entry.mismatched?(normalize_version(name, options))) || false
end
end Возвращает true если кэш содержит запись для данного ключа.
Параметры передаются в реализацию базового кэша.
# File activesupport/lib/active_support/cache.rb, line 349
def fetch(name, options = nil, &block)
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, event: payload) 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, &block)
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.
Установление skip_nil: true не будет кешировать значение nil:
cache.fetch('foo') { nil }
cache.fetch('bar', skip_nil: true) { nil }
cache.exist?('foo') # => true
cache.exist?('bar') # => false
Установка compress: false отключает сжатие записи в кэше.
Установление :expires_in установит время истечения срока действия для кэша. Все кэши поддерживают автоматическое истечение срока действия содержимого через заданное количество секунд. Это значение может быть указано как параметр конструктору (в этом случае все записи будут затронуты), или оно может быть передано методам fetch или write для воздействия только на одну запись. :expire_in и :expired_in являются псевдонимами для :expires_in.
cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes) cache.write(key, value, expires_in: 1.minute) # Set a lower value for one entry
Установка :expires_at установит абсолютное время истечения срока действия для кэша. Все кэши поддерживают автоматическое истечение срока действия содержимого через заданное количество секунд. Это значение может быть передано только методам fetch или write для воздействия только на одну запись.
cache = ActiveSupport::Cache::MemoryStore.new cache.write(key, value, expires_at: Time.now.at_end_of_hour)
Установка :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 469
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|
reads = read_multi_entries(names, **options)
writes = {}
ordered = names.index_with do |name|
reads.fetch(name) { writes[name] = yield(name) }
end
payload[:hits] = reads.keys
payload[:super_operation] = :fetch_multi
write_multi(writes, options)
ordered
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" }
Параметры передаются в реализацию базового кэша. Например:
cache.fetch_multi("fizz", expires_in: 5.seconds) do |key|
"buzz"
end
# => {"fizz"=>"buzz"}
cache.read("fizz")
# => "buzz"
sleep(6)
cache.read("fizz")
# => nil
# File activesupport/lib/active_support/cache.rb, line 556
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 219 def mute previous_silence, @silence = defined?(@silence) && @silence, true yield ensure @silence = previous_silence end
Отключает логирование внутри блока.
# File activesupport/lib/active_support/cache.rb, line 384
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, event: payload)
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 или :version, оба эти условия применяются перед возвратом данных.
Параметры передаются в реализацию базового кэша.
# File activesupport/lib/active_support/cache.rb, line 417
def read_multi(*names)
options = names.extract_options!
options = merged_options(options)
instrument :read_multi, names, options do |payload|
read_multi_entries(names, **options, event: payload).tap do |results|
payload[:hits] = results.keys
end
end
end Считывает несколько значений одновременно из кэша. Параметры могут быть переданы в последнем аргументе.
Некоторые реализации кэша могут оптимизировать этот метод.
Возвращает хэш, сопоставляющий предоставленные имена найденным значениям.
# File activesupport/lib/active_support/cache.rb, line 213 def silence! @silence = true self end
Выключает регистрирующий механизм.
# File activesupport/lib/active_support/cache.rb, line 494
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 429
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 Cache API хранения для записи нескольких значений сразу.
Приватные методы экземпляра
# File activesupport/lib/active_support/cache.rb, line 597
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–2021 David Heinemeier Hansson
Licensed under the MIT License.