domingo, 30 de noviembre de 2008

Expiration time en fragment caching

Cuando se usa el sistema de caché de rails se pueden elegir donde guardar los items cacheados, la mejor opción es la mayoría de los casos es memcached, pero no siempre tenemos posibilidad de instalar un demonio en la máquina que da hosting.

Otra posibilidad es guardar los items en el sistema de ficheros, para ello hay que añadir en el environment.rb lo siguiente.

config.cache_store = :file_store, '/path_to_cache'

El problema que tiene usar el sistema de ficheros como soporte para la cache es que no soporta la opción de expiración por tiempo, sin embargo memcached sí que lo hace.

Se puede solucionar añadiendo el siguiente parche al environment.rb

module ActiveSupport
module Cache
class FileStore < Store
def read(name, options = nil)
super
timestamp = File.open("#{real_file_path(name)}.timestamp", 'rb') { |f| f.read } rescue nil
if !timestamp or (timestamp and timestamp.to_i > Time.now.to_i)
File.open(real_file_path(name), 'rb') { |f| f.read } rescue nil
else
nil
end
end

def write(name, value, options = nil)
super
ensure_cache_path(File.dirname(real_file_path(name)))
if options and options[:expires_in]
File.open("#{real_file_path(name)}.timestamp", "wb+") { |f| f.write(Time.now.to_i + options[:expires_in].to_i) }
end
File.open(real_file_path(name), "wb+") { |f| f.write(value) }
rescue => e
RAILS_DEFAULT_LOGGER.error "Couldn't create cache directory: #{name} (#{e.message})" if RAILS_DEFAULT_LOGGER
end

def delete(name, options = nil)
super
File.delete("#{real_file_path(name)}.timestamp") rescue nil
File.delete(real_file_path(name)) rescue nil
end
end
end
end

Se puede utilizar al igual que la opción expires_in en memcached.

<% cache 'something', :expires_in => 5.minutes do %>
Hello, just saying hello from cache
<% end %>

Lo he desarrollado teniendo en cuenta la implementación de rails 2.1.2, y solo soporta fragment caching.

0 comentarios: