класс 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
Кэши также могут хранить значения в сжатом формате, чтобы экономить место и сократить время, затрачиваемое на отправку данных. Поскольку есть накладные расходы, значения должны быть достаточно большими, чтобы оправдать сжатие. Чтобы включить сжатие, передайте compress: true в инициализаторе или в качестве параметра к fetch или write. Чтобы указать порог, при котором значения будут сжиматься, установите параметр :compress_threshold. Пороговое значение по умолчанию составляет 16К.
Атрибуты
Публичные методы класса
# File activesupport/lib/active_support/cache.rb, line 161
def initialize(options = nil)
@options = options ? options.dup : {}
end Создаёт новый кэш. Параметры будут переданы любому методу записи, за исключением :namespace, который может быть использован для установки глобального пространства имён для кэша.
Публичные методы экземпляра
# File activesupport/lib/active_support/cache.rb, line 459
def cleanup(options = nil)
raise NotImplementedError.new("#{self.class.name} does not support cleanup")
end Очищает кэш, удаляя просроченные записи.
Параметры передаются в основную реализацию кэша.
Не все реализации могут поддерживать этот метод.
# File activesupport/lib/active_support/cache.rb, line 469
def clear(options = nil)
raise NotImplementedError.new("#{self.class.name} does not support clear")
end Очищает весь кэш. Будьте осторожны с этим методом, так как он может повлиять на другие процессы, если используется общий кэш.
Хэш параметров передается в основную реализацию кэша.
Не все реализации могут поддерживать этот метод.
# File activesupport/lib/active_support/cache.rb, line 450
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 407
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 432
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 418
def exist?(name, options = nil)
options = merged_options(options)
instrument(:exist?, name) do
entry = read_entry(normalize_key(name, options), options)
(entry && !entry.expired?) || false
end
end Возвращает true если кэш содержит запись для данного ключа.
Параметры передаются в основную реализацию кэша.
# File activesupport/lib/active_support/cache.rb, line 281
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)
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 сохранит большой набор записей кэша в сжатом формате.
Установка :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
Установка :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 376
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)
results = read_multi(*names, options)
names.each_with_object({}) do |name, memo|
memo[name] = results.fetch(name) do
value = yield name
write(name, value, options)
value
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 441
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 172 def mute previous_silence, @silence = defined?(@silence) && @silence, true yield ensure @silence = previous_silence end
Отключает логирование внутри блока.
# File activesupport/lib/active_support/cache.rb, line 311
def read(name, options = nil)
options = merged_options(options)
key = normalize_key(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
else
payload[:hit] = true if payload
entry.value
end
else
payload[:hit] = false if payload
nil
end
end
end Извлекает данные из кэша, используя заданный ключ. Если в кэше есть данные с заданным ключом, то эти данные возвращаются. В противном случае возвращается nil.
Параметры передаются в основную реализацию кэша.
# File activesupport/lib/active_support/cache.rb, line 338
def read_multi(*names)
options = names.extract_options!
options = merged_options(options)
results = {}
names.each do |name|
key = normalize_key(name, options)
entry = read_entry(key, options)
if entry
if entry.expired?
delete_entry(key, options)
else
results[name] = entry.value
end
end
end
results
end Считывает сразу несколько значений из кэша. Параметры могут быть переданы в последнем аргументе.
Некоторые реализации кэша могут оптимизировать этот метод.
Возвращает хэш, сопоставляющий предоставленные имена найденным значениям.
# File activesupport/lib/active_support/cache.rb, line 166 def silence! @silence = true self end
Отключает логирование.
# File activesupport/lib/active_support/cache.rb, line 395
def write(name, value, options = nil)
options = merged_options(options)
instrument(:write, name, options) do
entry = Entry.new(value, options)
write_entry(normalize_key(name, options), entry, options)
end
end Записывает значение в кэш с указанным ключом.
Параметры передаются в основную реализацию кэша.
Приватные методы экземпляра
# File activesupport/lib/active_support/cache.rb, line 478
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.