-
Notifications
You must be signed in to change notification settings - Fork 21.6k
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
ActiveSupport::Cache::Store(s) fails to autoload classes #8167
Comments
Hi @urielka. First of all, this bug report is really good, a model! Thanks for taking the time of writing it. This is a known gotcha. The underlying problem is that, as you mentioned, The traditional fix for that is to make sure cached classes are loaded before the cache is used. This is not what we'd call elegance though :). I think I believe Active Support could decorate I'd like to know the opinion of other core team members though, /cc @jeremy @NZKoz. |
Thanks! happy to help. The thing about this known gotcha is that is not documented anywhere(except blog posts) and breaks another feature of rails(autoloading). Even if the rescue clause causes performance problems it could be enabled if config.cache_classes is off or if Rails.env.development? I don't mind even writing a patch,should I do it on top of 3.2.x or 4? |
Historically we rescued LoadError, used regexps to pull out the missing constant from the error message, then re-tried the unmarshal. Pretty crazy stuff. I don't think 'performance problems' are a reason to remove that code, but 'that's crazy' is :). Perhaps as @urielka recommends you could just enable it for development mode or when cache_classes is off? |
Problem with that approach is that we do not eager load everything that's in For me, simply adding the rescue to try constantize is fine. |
The better long term fix would be for Marshal to call those hooks, but that's highly unlikely to change at this point. I've definitely no objection to the code being added, however it's trivial to work around in production mode, generally people only hit this in development when they're caching reloaded classes. |
The problem is indeed in development but I don't think that development should be treated as 2nd class citizen :) I don't think that in production this code should run at all,in production LoadError actually means that something is missing (assuming cache_classes is true). If there is no objection to the idea of adding this code,I can write a fix for this but I need to know on top of which branch to write it. |
Start on master, we can backport if the fix looks straightforward |
@urielka no, no, as I said before not all files in Do it simple, no conditionals. |
Will do :) |
If I use Kernel#autoload then Marshal.load works just fine and there is no need for this hack. @fxn : Why can't we just use Kernel#autoload ( or ActiveSupport::Autoload) for this? |
The constant autoloading mechanism cannot be implemented with There are a few reasons, some may have dirty workarounds (like the fact that If namespaces are implicit (there is only a directory in the file system) we could perhaps still do something because AS creates a module on the fly that we control, but when they do have a file that defines them we'd need to execute that file. And that opens a can of worms, because files are supposed to be loaded only on demand and that file in particular could use constants in the top-level. They could indeed trigger loading of child constants when your autoloads are not yet in place. |
Cool so I am testing this issue against ActiveSupport::Dependecies in my tests. I will post more as I progress. |
…t/dependecies.rb) (issue rails#8167)
Is there any plan to back-port this on Rails 3.2 ? |
…t/dependecies.rb) (issue rails#8167) Conflicts: activesupport/CHANGELOG.md activesupport/lib/active_support/cache/mem_cache_store.rb activesupport/test/caching_test.rb guides/source/active_support_core_extensions.md
I'm having this problem in my Rails 3.2 application. Rather than monkey patching Rails in my application to solve it, I would like to send a PR and have it fixed in the next minor. Would you be interested in merging that PR? |
Environment:
Steps to reproduce:
rails c
and then type this code:rails c
and type:Expected:
This should work like any other code that depends on Rails autoloading.
Actual:
It fails with the following error:
Why this is important?
This is important in development (in production config.cache_classes = true takes care of this) because if I just start my rails server and the first requests fetches some instance that the class wasn't already loaded (typical case the User object) it will crash.
I have seen other people ran into this problem and their conclusion was either enable config.cache_classes (yuck) or loading all the models at app start.
Note:
I used the class and not an instance as creating an instance requires creating a database table and I wanted to keep it simple.
It happens with instances too.
The source of this bug:
All stores (from what I checked) works with Marshal#load and it seems the autoloading mechanism in rails doesn't work for Marshal#load (I guess because it is native code)
Related links:
Other people that had this bug:
http://www.philsergi.com/2007/06/rails-memcached-undefinded-classmodule.html
http://stackoverflow.com/questions/4202352/memcached-problem-with-rails-3-object-isnt-being-deserialized-the-second-time
http://blog.endpoint.com/2012/08/rails-3-activerecord-caching-bug-ahoy.html
Possible solution:
http://stackoverflow.com/questions/3531588/memcached-as-an-object-store-in-rails
The text was updated successfully, but these errors were encountered: