Rails 3.2 Rack::Cache HTTP-заголовки и кэширование действий

Добрый день,

Я столкнулся с некоторыми проблемами, пытаясь объединить кэширование HTTP с Rack::Cache и кэшированием действий (в моем приложении, размещенном на Heroku).

Используя их по отдельности, кажется, что это работает. При включенном кэшировании действий страница загружается быстро, и журнал предполагает, что это кэширование. При кэшировании HTTP в контроллерах (eTag, last_modified и fresh_when) кажутся установленными правильные заголовки.

Однако, когда я пытаюсь объединить их, это похоже на кэширование действий, но заголовки HTTP всегда имеют значение max_age: 0, must_revalidate. Почему это? Я делаю что-то неправильно?

Например, вот код в моем «домашнем» действии:

class StaticPagesController < ApplicationController
  layout 'public'

  caches_action :about, :contact, ......, :home, .....

  ......

  def home
    last_modified = File.mtime("#{Rails.root}/app/views/static_pages/home.html.haml")
    fresh_when last_modified: last_modified , public: true, etag: last_modified
    expires_in 10.seconds, :public => true       
  end

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

$ curl -I http://myapp-staging.herokuapp.com/

HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Content-Type: text/html; charset=utf-8
Date: Thu, 24 May 2012 06:50:45 GMT
Etag: "997dacac05aa4c73f5a6861c9f5a9db0"
Status: 200 OK
Vary: Accept-Encoding
X-Rack-Cache: stale, invalid
X-Request-Id: 078d86423f234da1ac41b418825618c2
X-Runtime: 0.005902
X-Ua-Compatible: IE=Edge,chrome=1
Connection: keep-alive

Информация о конфигурации:

# Use a different cache store in production
config.cache_store = :dalli_store

config.action_dispatch.rack_cache = {
  :verbose      => true,
  :metastore => "memcached://#{ENV['MEMCACHE_SERVERS']}",
  :entitystore => "memcached://#{ENV['MEMCACHE_SERVERS']}"#,
}

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

ОБНОВЛЕНИЕ

Спасибо за ответ ниже! Кажется, это работает. Но чтобы не писать методы set_XXX_cache_header для каждого действия контроллера, видите ли вы причину, по которой это не сработает?

before_filter :set_http_cache_headers

.....

def set_http_cache_headers
  expires_in 10.seconds, :public => true
  last_modified = File.mtime("#{Rails.root}/app/views/static_pages/#{params[:action]}.html.haml")
  fresh_when last_modified: last_modified , public: true, etag: last_modified
end

person Brandon    schedule 31.05.2012    source источник


Ответы (1)


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

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

Итак, вы можете сделать что-то вроде этого:

class StaticPagesController < ApplicationController
  layout 'public'

  before_filter :set_home_cache_headers, :only => [:home]

  caches_action :about, :contact, ......, :home, .....

  ......

  def set_home_cache_headers
    last_modified = File.mtime("#{Rails.root}/app/views/static_pages/home.html.haml")
    fresh_when last_modified: last_modified , public: true, etag: last_modified
    expires_in 10.seconds, public: true       
  end
person Dan Weinand    schedule 03.07.2012
comment
Спасибо за отзыв! Я попробую и посмотрю, как это работает для меня. - person Brandon; 04.07.2012
comment
Кажется, это работает! Но у меня есть быстрый вопрос в обновлении, если вы не против проверить его (потенциальный способ избежать написания 18 отдельных методов). - person Brandon; 04.07.2012
comment
Обратите внимание, что before_filter нужно указывать ПЕРЕД вызовом caches_action (как показано выше), чтобы гарантировать, что фильтры запускаются в правильном порядке, так как это сначала сбило меня с толку. - person Stuart M; 04.01.2013