Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Session::DalliStore#get: Unable to unmarshal value: undefined class/module #129

Closed
chewi opened this issue Oct 11, 2011 · 9 comments
Closed

Comments

@chewi
Copy link

chewi commented Oct 11, 2011

I'm trying to use the Dalli session store with Rails 3.1.1. It seems to be unable to unmarshal my model classes. Apparently memcache-client (or the older memcache?) used to have the same problem but if I use :mem_cache_store with exactly the same arguments, it works fine. I can't see what it's doing differently to Dalli.

require 'action_dispatch/middleware/session/dalli_store'

Enchanted::Application.config.session_store :dalli_store, {
  :cache => Dalli::Client.new("localhost:11211", :namespace => "enchanted_#{Rails.env}_session"),
  :key => "_enchanted_#{Rails.env}_session",
  :expire_after => 2.hours
}

Nothing out of the ordinary here, I think. Here is how it was solved in the past but this is probably outdated now. The original server has gone as it is, hence the need for archive.org!

http://web.archive.org/web/20100910080153/http://kballcodes.com/2009/09/05/rails-memcached-a-better-solution-to-the-undefined-classmodule-problem/

@mperham
Copy link
Collaborator

mperham commented Oct 12, 2011

That blog post promotes a terrible hack and is exactly what you don't want to do. Better is to use require_dependency at the top of your controller so that Rails knows to load your model class before attempting to fetch it from memcached.

require_dependency 'user'

@mperham mperham closed this as completed Oct 12, 2011
@chewi
Copy link
Author

chewi commented Oct 12, 2011

I accept that the blog post is a hack but I don't think that's how it was officially fixed. I haven't seen anything like that in the Rails/Rack/memcache-client source. So why does it work for mem_cache_store?

@chewi
Copy link
Author

chewi commented Oct 12, 2011

I have several STI models in my application that all have to be required for this to work. Having to do this really goes against the Rails mantra. I've found out why it works for mem_cache_store and managed tweak to dalli_store to prove that it can work for this too. ActionDispatch::Session::MemCacheStore includes StaleSessionCheck. This is defined in abstract_store.rb. It wraps load_session in a rescue block that loads the classes as necessary. It is similar to the blog hack but it is officially part of Rails. Ugly but at least you won't be adding it yourself as it's already there. If you include StaleSessionCheck in ActionDispatch::Session::DalliStore, it still doesn't work because it only catches ArgumentError. This is what is originally thrown but Dalli replaces it with Dalli::DalliError and so it gets missed. You either need to pass through the ArgumentError unchanged or you need to wrap the ArgumentError instance so that it can be reraised in ActionDispatch::Session::DalliStore#get_session.

@mperham
Copy link
Collaborator

mperham commented Oct 12, 2011

I guess you learn something new every day. I didn't realize Rails had code to handle that edge case. Thanks for tracking it down for me!

@mperham mperham reopened this Oct 12, 2011
@dignoe
Copy link

dignoe commented May 1, 2012

Just a note... the way that this is currently implemented (and if you add require_dependency 'user' to the application controller), you get a big performance hit as it looks like Dalli is reloading the required classes at run time. I was caching some heavily used objects (i.e. Users), but got way better performance by just querying the database every time. I am also using the cache_fu gem, so it could be something to do with that as well.

@mperham
Copy link
Collaborator

mperham commented May 1, 2012

@dignoe Are you running in development mode?

@dignoe
Copy link

dignoe commented May 1, 2012

No, this was while running in Staging (same configs as Production... config.cache_classes = true). It does happen in development as well, but that is to be expected.

@mperham
Copy link
Collaborator

mperham commented May 1, 2012

FYI Dalli isn't doing anything but calling Marshal.load on the value. Rails might be reloading the class on each request but that has nothing to do with Dalli.

@dignoe
Copy link

dignoe commented May 1, 2012

Ok, thanks. I'm good with just querying the database for now. My message was more as an FYI, since others may come across the same situation if they're caching Ruby objects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants