martes, 6 de mayo de 2008

La caché (I)

Llevo algunos días viendo cosillas básicas de la caché de Rails. En concreto, he estado intentando cachear el resultado de una acción solicitada por Ajax cuyo resultado es renderizado por un archivo rjs. Y no ha habido manera. Hasta que recordando los tiempos en los que el 90% de mi tiempo lo dedicaba a depurar código Java sobre la plataforma Banksphere (todos tenemos un pasado oscuro) me metí un poquito en el código y llegué a caching.rb.

 private
  def caching_allowed
   request.get? && response.headers['Status'].to_i == 200
  end

Así que, por defecto, si una petición no se hace por GET no se cachea. Y las peticiones Ajax son POST de tó la vida.

Confiando un poquito más en el programador podemos cambiar la condición de cacheo por

 (request.get? || request.xhr?) && response.headers['Status'].to_i == 200

de forma que las peticiones Ajax, aún no siendo GET puedan cachearse.

Otro funcionamiento que no me convence es que el archivo cacheado se genera siempre y con extensión HTML. Entiendo que, una vez enganchado el resultado del cacheo (esto se podrá decir en castellano de algún modo mejor, no?) el hecho de que se genere siempre el archivo será irrelevante, pero se puede escribir una condición extra al método cache_page para que si el archivo existe no lo escriba:

  return if File.exists?(page_cache_path(path))

Respecto a que el archivo cacheado tenga extensión HTML creo recordar que se puede solucionar en la configuración de Apache, indicándole que el contenido de ciertos directorios se sirva como javascript, pero esto tengo que verlo.

Salud y rocanrol!

1 comentario:

Xavier Noria dijo...

Compañero.

En realidad Ajax puede ir por GET (no es mas que una peticion HTTP hecha con JavaScript), por ejemplo en link_to_remote se pasa :method => :get.

Si uno tiene el control del codigo lo propio es usar GET y POST cuando toca cada uno. En un caso como el de uso de cache es relevante, ya que una peticion POST no es cacheable porque en HTTP se usa POST para peticiones que cambian el estado en el servidor.

Por tanto, si uno controla el codigo lo suyo es usar la implementacion de cache normal y especificar :method => :get.

Si el codigo no es de uno y envia POST cuando queria decir GET ya hay que buscarse la vida porque el origen no esta fino.

En general se recomienda usar el plugin action_cache, entre otras cosas guarda los ficheros como YAML con las cabeceras del Response en lugar de los HTMLs.

Si el fichero se regeneraba lo mas probable es que no se este sirviendo la cache de hecho. Porque, tu sabes, una cache en Rails se genera una sola vez y la gracia esta en que no se invoca a la accion hasta que la aplicacion no invalide la cache.