Как кэшировать файлы более 1 МБ с помощью rack / cache на Heroku?

Я использую комбинацию Стрекоза и стойки/кэш размещенного на Heroku.

Я использую Dragonfly для загруженных активов. Миниатюры обрабатываются на лету и хранятся в стойке / кэше для быстрой доставки из memcached (через Memcachier аддон).

регулярные статические активы также кэшируются в memcached через rack / cache.

моя проблема в том, что любые загруженные файлы более 1 МБ вызывают ошибку 500 в моем приложение.

2013-07-15T10:38:27.040992+00:00 app[web.1]: DalliError: Value too large, memcached can only store 1048576 bytes per key [key: d49c36d5db74ef45e957cf169a0b27b83b9e84de, size: 1502314]
2013-07-15T10:38:27.052255+00:00 app[web.1]: cache: [GET /media/BAhbBlsHOgZmSSIdNTA3Njk3ZWFiODBmNDEwMDEzMDAzNjA4BjoGRVQ/WTW_A5Flyer_HealthcareMedicalObsGynae_WEB.pdf] miss, store
2013-07-15T10:38:27.060583+00:00 app[web.1]: !! Unexpected error while processing request: undefined method `each' for nil:NilClass

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

Я даже не уверен, откуда эта ошибка. Предположительно, от одного из других промежуточных устройств rack?

увеличение максимального размера файла, похоже, не влияет.

config.cache_store = :dalli_store, ENV["MEMCACHIER_SERVERS"].split(","), {¬
  :username        => ENV["MEMCACHIER_USERNAME"],¬
  :password        => ENV["MEMCACHIER_PASSWORD"],¬
  :value_max_bytes => 5242880 # 5MB¬
}

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

что я могу сделать, чтобы обслуживать эти активы на Heroku, в то же время без ошибок?

3 ответов


у меня была та же проблема, что и @jordelver, и мне удалось обойти пределы memcachier, исправив обезьяну Dragonfly::Response:

module Dragonfly
  class Response
    private
    def cache_headers
      if job.size > 1048576
        {
          "Cache-Control" => "no-cache, no-store",
          "Pragma" => "no-cache"
        }
      else
        {
           "Cache-Control" => "public, max-age=31536000", # (1 year)
           "ETag" => %("#{job.signature}")
        }
      end
    end
  end
end

по существу, если размер превышает 1048576 байт, отправьте заголовок без кэша.


Так вопреки вопросу @jordelver, я нахожу, что установка :value_max_bytes опция dalli работает. Я настраиваю Rack:: Cache немного по-другому, что, возможно, имеет значение.

Это то, что моя production.rb содержит для настройки Rack:: Cache:

client = Dalli::Client.new(ENV["MEMCACHIER_SERVERS"],
                           :username => ENV["MEMCACHIER_USERNAME"],
                           :password => ENV["MEMCACHIER_PASSWORD"],
                           :value_max_bytes => 10485760)
config.action_dispatch.rack_cache = {
  :metastore    => client,
  :entitystore  => client
}
config.static_cache_control = "public, max-age=2592000"

с вышеизложенным некоторые ошибки будут напечатаны в журналах для значений более 1 МБ, но они не вызовут ошибку 5xx для клиента, просто пропуск кэша.

P. S Я работаю на MemCachier:) Итак мы заинтересованы в том, чтобы разобраться с этим. Пожалуйста, дайте мне знать, если это работает.


мой application.js был слишком велик для rack-cache Так я и сделал:

# in config/environments/development.rb
config.action_dispatch.rack_cache = {
  metastore: 'file:/var/cache/rack/meta',
  entitystore: 'file:tmp/cache/rack/body'
}

и это работает!

хранит метаданные в memcache, но фактический файл в файловой системе, а не в памяти.