Rails 3.2 Rack::Cache HTTP Headers y Action Caching

Buenas tardes,

Me he encontrado con algunos problemas al intentar combinar el almacenamiento en caché HTTP con Rack::Cache y el almacenamiento en caché de acciones (en mi aplicación alojada en Heroku).

Usándolos individualmente, parece estar funcionando. Con el almacenamiento en caché de acciones habilitado, la carga de la página es rápida y el registro sugeriría que se está almacenando en caché. Con el almacenamiento en caché de HTTP en los controladores (eTag, last_modified y fresh_when), los encabezados adecuados parecen estar configurados.

Sin embargo, cuando trato de combinar los dos, parece ser un almacenamiento en caché de acciones, pero los encabezados HTTP siempre son max_age: 0, must_revalidate. ¿Por qué es esto? ¿Estoy haciendo algo mal?

Por ejemplo, aquí está el código en mi acción "inicio":

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

Para todos los efectos, esto debería tener una etiqueta pública de control de caché con una edad máxima de 10 años, ¿no?

$ 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

Información de configuración:

# 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']}"#,
}

En mi opinión, debería poder usar el almacenamiento en caché de acciones, así como un proxy inverso, ¿correcto? Sé que hacen cosas bastante similares (si la página cambia, tanto el proxy como el caché de acciones no serán válidos y deberán regenerarse), pero creo que debería poder tener ambos allí. ¿O debería deshacerme de uno?

ACTUALIZACIÓN

¡Gracias por la respuesta a continuación! Parece funcionar. Pero para evitar tener que escribir métodos set_XXX_cache_header para cada acción del controlador, ¿ve alguna razón por la que esto no funcione?

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

preguntado el 31 de mayo de 12 a las 01:05

1 Respuestas

Cuando utiliza el almacenamiento en caché de acciones, solo se almacenan en caché el cuerpo de la respuesta y el tipo de contenido. Cualquier otro cambio en la respuesta no ocurrirá en las solicitudes posteriores.

Sin embargo, el almacenamiento en caché de acciones ejecutará cualquier filtro anterior incluso cuando la acción en sí esté almacenada en caché.

Entonces, puedes hacer algo como esto:

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

Respondido 03 Jul 12, 20:07

¡Gracias por el aporte! Le daré una oportunidad y veré cómo funciona para mí. - Brandon

¡Esto parece estar funcionando! Pero tengo una pregunta rápida en la actualización si no le importa verificarla (una forma potencial de evitar escribir 18 métodos separados). - Brandon

Tenga en cuenta que before_filter necesita estar en la lista ANTES de la llamada a caches_action (como se muestra arriba) para garantizar que los filtros se ejecuten en el orden correcto, ya que eso me hizo tropezar al principio. - Estuardo M

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.