Spec-Zone.ru › Ruby on Rails 7.1

класс ActiveSupport::Cache::Store

Родитель:
Объект

Класс Active Support Cache Store

Абстрактный класс хранилища кэша. Существует множество реализаций хранилищ кэша, каждая со своими дополнительными функциями. Смотрите классы в модуле ActiveSupport::Cache, например, ActiveSupport::Cache::MemCacheStore. MemCacheStore в настоящее время является самым популярным хранилищем кэша для крупных веб-сайтов в производстве.

Некоторые реализации могут не поддерживать все методы, кроме основных методов кэша fetch, write, read, exist? и delete.

ActiveSupport::Cache::Store может хранить любые объекты Ruby, которые поддерживаются методами coder и dump его load.

cache = ActiveSupport::Cache::MemoryStore.new

cache.read('city')   # => nil
cache.write('city', "Duckburgh")
cache.read('city')   # => "Duckburgh"

cache.write('not serializable', Proc.new {}) # => TypeError

Ключи всегда преобразуются в строки и регистрозависимы. Если для объекта, заданного в качестве ключа, определён метод cache_key, этот метод будет вызван для определения ключа. В противном случае будет вызван метод to_param. Массивы и хэши также могут использоваться в качестве ключей. Элементы будут разделяться косыми чертами, а элементы в Hash будут отсортированы по ключу для согласованности.

cache.read('city') == cache.read(:city)   # => true

Значения Nil могут быть кэшированы.

Если ваш кэш находится на общей инфраструктуре, вы можете определить имя пространства для ваших записей в кэше. Если имя пространства определено, оно будет добавляться в префикс к каждому ключу. Имя пространства может быть либо статическим значением, либо процедурой. Если это процедура, она будет вызываться при оценке каждого ключа, чтобы вы могли использовать логику приложения для аннулирования ключей.

cache.namespace = -> { @last_mod_time }  # Set the namespace to a variable
@last_mod_time = Time.now  # Invalidate the entire cache by changing namespace

Атрибуты

options[R]
silence[R]
silence?[R]

Публичные методы класса

new(options = nil) Показать исходный код
# File activesupport/lib/active_support/cache.rb, line 319
def initialize(options = nil)
  @options = options ? validate_options(normalize_options(options)) : {}

  @options[:compress] = true unless @options.key?(:compress)
  @options[:compress_threshold] ||= DEFAULT_COMPRESS_LIMIT

  @coder = @options.delete(:coder) do
    legacy_serializer = Cache.format_version < 7.1 && !@options[:serializer]
    serializer = @options.delete(:serializer) || default_serializer
    serializer = Cache::SerializerWithFallback[serializer] if serializer.is_a?(Symbol)
    compressor = @options.delete(:compressor) { Zlib }

    Cache::Coder.new(serializer, compressor, legacy_serializer: legacy_serializer)
  end

  @coder ||= Cache::SerializerWithFallback[:passthrough]

  @coder_supports_compression = @coder.respond_to?(:dump_compressed)
end

Создаёт новый кэш.

Параметры

:namespace

Устанавливает имя пространства для кэша. Этот параметр особенно полезен, если ваше приложение использует общий кэш с другими приложениями.

:serializer

Сериализатор для кэшированных значений. Должен поддерживать методы dump и load.

По умолчанию используется сериализатор, зависящий от версии формата кэша (установленной через config.active_support.cache_format_version при использовании Rails). По умолчанию сериализатор для каждой версии формата включает механизм обратной совместимости для десериализации значений из любой версии формата. Это позволяет легко мигрировать между версиями форматов без аннулирования всего кэша.

Вы также можете указать serializer: :message_pack для использования предварительно настроенного сериализатора на основе ActiveSupport::MessagePack. Сериализатор :message_pack включает тот же механизм обратной совместимости при десериализации, что позволяет легко мигрировать из (или в) стандартный сериализатор. Сериализатор :message_pack может повысить производительность, но требует наличия gem msgpack.

:compressor

Компрессор для сериализованных значений кэша. Должен поддерживать методы deflate и inflate.

По умолчанию используется компрессор Zlib. Чтобы определить новый пользовательский компрессор, который также декомпрессирует старые записи кэша, можно проверить сжатые значения на наличие подписи Zlib "\x78".

module MyCompressor
  def self.deflate(dumped)
    # compression logic... (make sure result does not start with "\x78"!)
  end

  def self.inflate(compressed)
    if compressed.start_with?("\x78")
      Zlib.inflate(compressed)
    else
      # decompression logic...
    end
  end
end

ActiveSupport::Cache.lookup_store(:redis_cache_store, compressor: MyCompressor)
:coder

Кодер для сериализации и (необязательно) сжатия записей кэша. Должен поддерживать методы dump и load.

По умолчанию используется кодер, объединяющий сериализатор и компрессор, и включающий некоторые оптимизации производительности. Если вам нужно только переопределить сериализатор или компрессор, вы должны указать параметры :serializer или :compressor соответственно.

Если хранилище может обрабатывать записи кэша непосредственно, вы также можете указать coder: nil для пропуска сериализатора, компрессора и кодера. Например, если вы используете ActiveSupport::Cache::MemoryStore и можете гарантировать, что значения кэша не будут изменены, вы можете указать coder: nil для избежания накладных расходов, связанных с защитой от изменений.

Параметр :coder является взаимоисключающим с параметрами :serializer и :compressor. Их одновременное указание приведёт к исключению ArgumentError.

Любые другие указанные параметры обрабатываются как параметры по умолчанию для соответствующих операций кэша, таких как read, write и fetch.

Публичные методы экземпляра

cleanup(options = nil) Show source
# File activesupport/lib/active_support/cache.rb, line 747
def cleanup(options = nil)
  raise NotImplementedError.new("#{self.class.name} does not support cleanup")
end

Очищает кэш, удаляя устаревшие записи.

Параметры передаются базовой реализации кэша.

Некоторые реализации могут не поддерживать этот метод.

clear(options = nil) Show source
# File activesupport/lib/active_support/cache.rb, line 757
def clear(options = nil)
  raise NotImplementedError.new("#{self.class.name} does not support clear")
end

Очищает весь кэш. Будьте осторожны с этим методом, так как он может повлиять на другие процессы, если используется общий кэш.

Хэш параметров передается базовой реализации кэша.

Некоторые реализации могут не поддерживать этот метод.

decrement(name, amount = 1, options = nil) Show source
# File activesupport/lib/active_support/cache.rb, line 738
def decrement(name, amount = 1, options = nil)
  raise NotImplementedError.new("#{self.class.name} does not support decrement")
end

Уменьшает целочисленное значение в кэше.

Параметры передаются базовой реализации кэша.

Некоторые реализации могут не поддерживать этот метод.

delete(name, options = nil) Show source
# File activesupport/lib/active_support/cache.rb, line 676
def delete(name, options = nil)
  options = merged_options(options)

  instrument(:delete, name) do
    delete_entry(normalize_key(name, options), **options)
  end
end

Удаляет запись в кэше. Возвращает true если запись удалена и false в противном случае.

Параметры передаются базовой реализации кэша.

delete_matched(matcher, options = nil) Show source
# File activesupport/lib/active_support/cache.rb, line 720
def delete_matched(matcher, options = nil)
  raise NotImplementedError.new("#{self.class.name} does not support delete_matched")
end

Удаляет все записи с ключами, соответствующими шаблону.

Параметры передаются базовой реализации кэша.

Некоторые реализации могут не поддерживать этот метод.

delete_multi(names, options = nil) Show source
# File activesupport/lib/active_support/cache.rb, line 688
def delete_multi(names, options = nil)
  return 0 if names.empty?

  options = merged_options(options)
  names.map! { |key| normalize_key(key, options) }

  instrument_multi :delete_multi, names do
    delete_multi_entries(names, **options)
  end
end

Удаляет несколько записей в кэше. Возвращает количество удаленных записей.

Параметры передаются базовой реализации кэша.

exist?(name, options = nil) Show source
# File activesupport/lib/active_support/cache.rb, line 702
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 если кэш содержит запись для данного ключа.

Параметры передаются базовой реализации кэша.

fetch(name, options = nil, &block) Show source
# File activesupport/lib/active_support/cache.rb, line 452
def fetch(name, options = nil, &block)
  if block_given?
    options = merged_options(options)
    key = normalize_key(name, options)

    entry = nil
    unless options[:force]
      instrument(:read, name, options) do |payload|
        cached_entry = read_entry(key, **options, event: payload)
        entry = handle_expired_entry(cached_entry, key, options)
        if entry
          if entry.mismatched?(normalize_version(name, options))
            entry = nil
          else
            begin
              entry.value
            rescue DeserializationError
              entry = nil
            end
          end
        end
        payload[:super_operation] = :fetch if payload
        payload[:hit] = !!entry if payload
      end
    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"

Параметры

Внутренне, fetch вызывает read_entry и вызывает write_entry при промахе кэша. Таким образом, fetch поддерживает те же параметры, что и read и write. Кроме того, fetch поддерживает следующие параметры:

  • force: true - Принудительно создает промах кэша, то есть мы рассматриваем значение кэша как отсутствующее, даже если оно присутствует. Передача блока обязательна, когда force истинно, поэтому это всегда приводит к записи в кэш.

    cache.write('today', 'Monday')
    cache.fetch('today', force: true) { 'Tuesday' } # => 'Tuesday'
    cache.fetch('today', force: true) # => ArgumentError
    

    Параметр :force полезен, когда вы вызываете какой-либо другой метод, чтобы узнать, следует ли принудительно выполнить запись в кэш. В противном случае, понятнее просто вызвать write.

  • skip_nil: true - Предотвращает кэширование результата nil:

    cache.fetch('foo') { nil }
    cache.fetch('bar', skip_nil: true) { nil }
    cache.exist?('foo') # => true
    cache.exist?('bar') # => false
    
  • :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"
    

Динамические параметры

В некоторых случаях может потребоваться динамически вычислять параметры на основе кэшированного значения. Для поддержки этого экземпляр ActiveSupport::Cache::WriteOptions передается во второй аргумент блока. Например:

cache.fetch("authentication-token:#{user.id}") do |key, options|
  token = authenticate_to_service
  options.expires_at = token.expires_at
  token
end
fetch_multi(*names) { |name| ... } Show source
# File activesupport/lib/active_support/cache.rb, line 601
def fetch_multi(*names)
  raise ArgumentError, "Missing block: `Cache#fetch_multi` requires a block." unless block_given?
  return {} if names.empty?

  options = names.extract_options!
  options = merged_options(options)

  instrument_multi :read_multi, names, options do |payload|
    if options[:force]
      reads = {}
    else
      reads = read_multi_entries(names, **options)
    end

    writes  = {}
    ordered = names.index_with do |name|
      reads.fetch(name) { writes[name] = yield(name) }
    end
    writes.compact! if options[:skip_nil]

    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" }

Вы также можете указать дополнительные параметры через аргумент options. См. fetch для подробностей. Другие параметры передаются базовой реализации кэша. Например:

cache.fetch_multi("fizz", expires_in: 5.seconds) do |key|
  "buzz"
end
# => {"fizz"=>"buzz"}
cache.read("fizz")
# => "buzz"
sleep(6)
cache.read("fizz")
# => nil
increment(name, amount = 1, options = nil) Show source
# File activesupport/lib/active_support/cache.rb, line 729
def increment(name, amount = 1, options = nil)
  raise NotImplementedError.new("#{self.class.name} does not support increment")
end

Увеличивает целочисленное значение в кэше.

Параметры передаются базовой реализации кэша.

Некоторые реализации могут не поддерживать этот метод.

mute() { || ... } Show source
# File activesupport/lib/active_support/cache.rb, line 346
def mute
  previous_silence, @silence = defined?(@silence) && @silence, true
  yield
ensure
  @silence = previous_silence
end

Отключает ведение журнала внутри блока.

read(name, options = nil) Show source
# File activesupport/lib/active_support/cache.rb, line 506
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
        begin
          entry.value
        rescue DeserializationError
          payload[:hit] = false
          nil
        end
      end
    else
      payload[:hit] = false if payload
      nil
    end
  end
end

Считывает данные из кэша, используя заданный ключ. Если в кэше есть данные с заданным ключом, то эти данные возвращаются. В противном случае возвращается nil.

Обратите внимание, если данные были записаны с параметрами :expires_in или :version, оба этих условия применяются перед возвратом данных.

Параметры

  • :namespace - Заменить пространство имен хранилища для этого вызова.

  • :version - Указывает версию для записи кэша. Если кэшированная версия не соответствует запрошенной версии, чтение будет рассматриваться как промах кэша. Эта функция используется для поддержки многоразовых ключей кэша.

Другие параметры будут обрабатываться конкретной реализацией хранилища кэша.

read_multi(*names) Show source
# File activesupport/lib/active_support/cache.rb, line 544
def read_multi(*names)
  return {} if names.empty?

  options = names.extract_options!
  options = merged_options(options)

  instrument_multi :read_multi, names, options do |payload|
    read_multi_entries(names, **options, event: payload).tap do |results|
      payload[:hits] = results.keys
    end
  end
end

Считывает несколько значений одновременно из кэша. Параметры могут быть переданы в последнем аргументе.

Некоторые реализации кэша могут оптимизировать этот метод.

Возвращает хэш, сопоставляющий предоставленные имена найденным значениям.

silence!() Показать исходный код
# File activesupport/lib/active_support/cache.rb, line 340
def silence!
  @silence = true
  self
end

Выключает регистратор.

write(name, value, options = nil) Показать исходный код
# File activesupport/lib/active_support/cache.rb, line 663
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

Записывает значение в кэш с указанным ключом. Значение должно поддерживаться методами coder‘s dump и load.

По умолчанию, записи в кэше, превышающие 1 КБ, сжимаются. Сжатие позволяет хранить больше данных в том же объёме памяти, что приводит к меньшему числу вытеснений из кэша и более высоким показателям попаданий.

Опции

  • compress: false - Отключает сжатие записи в кэше.

  • :compress_threshold - Порог сжатия, указанный в байтах. Записи в кэше, превышающие этот порог, будут сжаты. По умолчанию 1.kilobyte.

  • :expires_in - Устанавливает относительное время истечения срока действия для записи в кэше, указанное в секундах. :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 - Устанавливает абсолютное время истечения срока действия для записи в кэше.

    cache = ActiveSupport::Cache::MemoryStore.new
    cache.write(key, value, expires_at: Time.now.at_end_of_hour)
    
  • :version - Указывает версию для записи в кэше. При чтении из кэша, если версия в кэше не совпадает с запрошенной версией, чтение будет обрабатываться как промах кэша. Эта функция используется для поддержки повторно используемых ключей кэша.

Другие опции будут обработаны конкретной реализацией хранилища кэша.

write_multi(hash, options = nil) Показать исходный код
# File activesupport/lib/active_support/cache.rb, line 558
def write_multi(hash, options = nil)
  return hash if hash.empty?

  options = merged_options(options)

  instrument_multi :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 хранилища для записи нескольких значений сразу.

Приватные методы экземпляра

key_matcher(pattern, options) Показать исходный код
# File activesupport/lib/active_support/cache.rb, line 785
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.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API