This project is archived and is in readonly mode.
Rails.cache freezes all objects passed to it
Reported by Matthew Beale | May 15th, 2009 @ 11:35 PM | in 3.x
A changeset and a file:
http://github.com/rails/rails/commit/5de340e79f1d11973b7c7bbec82f32...
http://github.com/rails/rails/blob/2e69db18ce2815c25eee64fc2978e7f6...
Local cache uses MemoryStore, and MemoryStore freezes everything it stores. Local cache is used on all caches, so any object written to any store will be frozen:
(rdb:43) Rails.cache
#<ActiveSupport::Cache::MemCacheStore:0xb70a46e8 @data=<MemCache: 1 servers, 1 buckets, ns: "greatspace", ro: false>, @addresses=["localhost"], @middleware=#<Class:0xb7051a9c>, @thread_local_key=:active_support_cache_mem_cache_store_local_cache>
(rdb:43) my_obj.frozen?
false
(rdb:43) Rails.cache.write("myobjs_#{my_obj.id}", my_obj, :expires_in => 1.day)
false
(rdb:43) my_obj.frozen?
true
This is a pretty significant change in behavior and really hard to track down. I had a method changing an instance variable telling me the object was frozen in prod. Is it intentional?
I'm going to work up a test. For a fix MemoryStore could just be dropped from local_cache in favor of something less intrusive. Or objects could be duped going into the cache? I haven't come up with anything great.
@josh peek you've touched a bunch of this code. Thoughts?
Comments and changes to this ticket
-
soulware May 23rd, 2009 @ 01:12 AM
Hi,
this does not even seem to be a simple change in behavior for Rails 2.3
The following code in a controller action -
puts "1st pass: #{Rails.cache.fetch("key"){Item.find(1)}.frozen?}"
puts "2nd pass: #{Rails.cache.fetch("key"){Item.find(1)}.frozen?}"Gives this -
1st pass: true
2nd pass: falseThe first time something is pulled from the per-request local cache it is frozen. Any further times it is pulled in that request it is not frozen.
I do not believe this is intentional behavior as the freeze does not seem consistent.
-
soulware May 23rd, 2009 @ 01:18 AM
Try again with formatting...
The following code in a controller action -
puts "1st pass: #{Rails.cache.fetch("key"){Item.find(1)}.frozen?}"
puts "2nd pass: #{Rails.cache.fetch("key"){Item.find(1)}.frozen?}"Gives this -
1st pass: true
2nd pass: false -
soulware May 23rd, 2009 @ 01:19 AM
And again...
The following code in a controller action -
puts "1st pass: #{Rails.cache.fetch("key"){Item.find(1)}.frozen?}" puts "2nd pass: #{Rails.cache.fetch("key"){Item.find(1)}.frozen?}"
Gives this -
1st pass: true 2nd pass: false
-
Guoliang Cao May 26th, 2009 @ 09:20 PM
We introduced Memcached to our project in previous release and upgraded to Rails 2.3.2 in current release. "Can't modify frozen object" is causing headache now. Is freezing object intended behavior? Can we let the application to worry about whether it is appropriate to modify cached object? Please let us know. Thank you.
-
Matthew Beale June 3rd, 2009 @ 07:07 PM
#2303 is close, but that's testing things read from the cache are not frozen, the issue here is things being written are frozen.
That's a really helpful changeset for seeing how I might make a test for this though, cool.
-
soulware June 3rd, 2009 @ 09:32 PM
I think the expected behavior is for everything in the cache to be frozen. The fix from #2302 ensures that things pulled from the cached are duped so the client is given an unfrozen version, ensuring the version in the cache remains unchanged.
-
Timur Vafin September 25th, 2009 @ 10:52 AM
Yep guys,
could anybody push rails team for that?Thanks,
Timur -
Bart Zonneveld October 13th, 2009 @ 04:29 PM
Confirmed, still occuring in 2.3.4, so a big +1 from me too.
-
scottwb August 7th, 2010 @ 09:37 PM
- Importance changed from to
Still not fixes on 2.3.8...
I forked the rails repository and made a topic branch that cherry-picked in the two related commits that were made back in July 2009 to address this (but never got merged back into 2-3-stable), plus I added one more change to dup the MemoryStore-cached object on the way back out too, to make it behave more like MemCacheStore. (Rationale for this explained here: http://sleeplesscoding.blogspot.com/2010/08/rails-23-activesupportc...)
I believe this would address everyone's problems on this thread. If there's a 2.3.9 in our future, I'd love to see this topic branch incorporated. I submitted a pull request for this.
-
Ralph Haygood August 18th, 2010 @ 10:30 PM
I too would be happy if this misfeature went away, without my having to hack it out myself.
-
ehud (at playedonline) October 26th, 2010 @ 09:46 AM
This is also relevant to Rails 3.x, and seems like a very odd change in the cache's behavior.
We use memcache to store ActiveRecord objects, updating their attributes and only save them to the db in certain intervals. I can't see how freezing all objects read from cache makes sense for a lot of use cases. For the time being we're monkey patching Cache.rb to not freeze the returned value. Is there a downside to that anyone can think of? -
Santiago Pastorino February 2nd, 2011 @ 04:20 PM
- State changed from new to open
This issue has been automatically marked as stale because it has not been commented on for at least three months.
The resources of the Rails core team are limited, and so we are asking for your help. If you can still reproduce this error on the 3-0-stable branch or on master, please reply with all of the information you have about it and add "[state:open]" to your comment. This will reopen the ticket for review. Likewise, if you feel that this is a very important feature for Rails to include, please reply with your explanation so we can consider it.
Thank you for all your contributions, and we hope you will understand this step to focus our efforts where they are most helpful.
-
Santiago Pastorino February 2nd, 2011 @ 04:20 PM
- State changed from open to stale
-
Michael Kintzer February 2nd, 2011 @ 11:49 PM
Seems to be still an issue with Rails 3.0.3. Using memcache store or redis store. This code in ActiveSupport::Cache
# Get the value stored in the cache.
def value if @value val = compressed? ? Marshal.load(Zlib::Inflate.inflate(@value)) : @value unless val.frozen? val.freeze rescue nil end val end end</code>
-
Xavier Noria February 16th, 2011 @ 10:05 AM
- Assigned user set to Xavier Noria
I was caught by this one today.
I have two around filters: the first one configured in ApplicationController yields to be able to inject a tracking code for Google Analytics later. A second around filter, down in some particular controller, caches an action response.
Since writing freezes the body, the tracking code can't be injected.
I see no reason why the write method has to mess with the frozen flag at all, it is your business whether that object can be later modified.
Unless someone can present a good rationale for this, I'll change this behavior as discussed in this ticket.
-
mdrozdziel March 22nd, 2011 @ 12:49 PM
Is this patched in any official release of Rails? If not, can you provide any kind of monkey-patch temporary fix, or something? Thanks in advance.
-
mdrozdziel March 22nd, 2011 @ 01:18 PM
I just found this: http://sleeplesscoding.blogspot.com/2010/08/rails-23-activesupportc...
Last comment is scary...
-
John Berry April 5th, 2011 @ 01:27 AM
Just a +1 for Xavier's comment and approach above. This is causing us major headaches during an upgrade from Rails 2.1 and we'd prefer to be in control of whether the cached objects are frozen or not.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>