MemCache + STI

Buenas!

A ver si me pueden dar una manito con esto. Estoy intentando utilizar el
plugin Interlock [1] para cachear objetos en MemCache combinado con un
modelo de datos basado en Single-Table Inheritance (STI).

El modelo es bastante simple:
Post < ActiveRecord
MicroblogPost < Post
ImagePost < Post

Interlock provee “Caching finders”, que hace uso del method
overloading de Ruby sobre los “find” de ActiveRecord. Por lo tanto si le
pasamos un entero o un set, Interlock automáticamente los almacenará en
MemCache para futuros accesos.

El problema es cuando intento utilizar un modelo que hereda de otro.
Por ejemplo:

Post.find(1000,2000,3000)
ArgumentError: undefined class/module MicroblogPost
from
/var/lib/gems/1.8/gems/memcache-client-1.5.0/lib/memcache.rb:262:in
load' from /var/lib/gems/1.8/gems/memcache-client-1.5.0/lib/memcache.rb:262:inget_multi’
from
/var/lib/gems/1.8/gems/memcache-client-1.5.0/lib/memcache.rb:261:in
`each’

Sin embargo si hago un “MicroblogPost.find(1000)” funciona
correctamente, e incluso a partir de ese momento funcionaría tambien
“Post.find(1000)”

Con el Post.find(2000) volvería a fallar porque puede ser un ImagePost y
vuelta a empezar.

He leído [2] que probablemente tenga que hacer un “require_dependency
‘post’” para volver a cargar el modelo en cada request, pero el tema es
que tampoco funciona en mi caso.

Lo único que he encontrado útil ha sido un post [3] que implementa un
before_filter para precargar los modelos que heredan de Post (en mi
caso) antes de cada request, pero como bien dice el mismo autor, no deja
de ser un hack.

Comentarios, ideas, experiencias esotéricas similares? :slight_smile:

Gracias de antemano,
Mauro.

:wq

[1]
http://blog.evanweaver.com/files/doc/fauna/interlock/files/README.html
[2] http://wiki.rubyonrails.org/rails/pages/singletableinheritance
[3]
http://www.philsergi.com/2007/06/rails-memcached-undefinded-classmodule.html

hola,

Post.find(1000,2000,3000)

ArgumentError: undefined class/module MicroblogPost
from

Eso pasa porque Marshal.load intenta deserializar un objeto de una clase
que no está cargada en memoria. Según como tengas montada tu aplicación
bastaría con arrancar en modo production, de esa forma una vez se carga
una clase en memoria ya se queda ahí, y cuando se intenta deserializar
la encuentras.

El problema de esto es si has serializado el objeto con un mongrel y lo
intentas deserializar desde la caché con otro que todavía nunca usó esa
clase (porque estás en cluster, o porque has reiniciado pero sin limpiar
la caché). Para ese caso te seguiría fallando.

Lo único que he encontrado útil ha sido un post [3] que implementa un
before_filter para precargar los modelos que heredan de Post (en mi

yo utilizo algo muy parecido a eso, lo que pasa es que en lugar de un
before_filter lo ejecuto directamente antes de llamar al get de la gema
memcache_client, y solamente le llamo una vez si estoy en modo
production o en cada ejecución en modo development.

Tengo este trozo de código


def self.preload_models
#we need to reference the classes here so if coming from cache
Marshal.load will find them
ActiveRecord::Base.connection.tables.each do |model|
begin
“#{model.classify}”.constantize
rescue Exception
nil
end
end
end

self.preload_models #we need to reference all the models, just in case

Con eso defino el método que precarga los modelos y le llamo una vez,
que para el caso de production ya los cargaría y no sería necesario
llamarlo más.

y luego antes de hacer el get a memcached tengo esto


self.preload_models if Dependencies.mechanism == :load #load all the
references every time if not caching classes

que en el caso de desarrollo hace que se llame cada vez a los modelos

Y con eso funciona correctamente

saludos,

javier ramírez

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs