-
Notifications
You must be signed in to change notification settings - Fork 99
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
Global cache flush #25
Comments
+1 |
I did this for now, seems faster but doesn't support instances (which is OK for specs, I guess): require 'binding_of_caller'
require 'memoist'
module Memoist
@@_classes = Set.new
alias old_memoize memoize
def memoize(*method_names)
@@_classes << if self.singleton_class?
binding.callers[2].receiver
else
self
end
old_memoize(*method_names)
end
def self.flush_cache
@@_classes.each { |x| x.try(:flush_cache) }
end
end
# spec_helper
config.after(:each) do
Memoist.flush_cache
end |
Can you do ObjectSpace.each_object(Memoist) { |o| o.flush_cache } I believe each class that extends memoist should be handled by that... It should be faster |
This is interesting. You don't want to retain a list of all memoised objects, or else they can't be garbage collected. But you could selectively add objects to a list Something like memoize :foo, track: true But Id say, if you`re memoizing a whole bunch of global objects, If you handcoded your class class Foo
def self.bar
@bar ||= something_you_want_to_memoizr
end
end How would you flush that? |
Bumping a 5 year old issue! 💯 We're not having issues with memoized instances leaking between specs, but we've hit a nasty bit of dependency using class-level memoization. Here's our solution (currently sits in our spec code but can be extracted):
Class memoization occurs at the singleton class level, but This approach doesn't introduce the GC issues of tracking every memoized object, but constantly scanning ObjectSpace for classes isn't the most efficient approach either... you need to check after each spec if you're you're not preloading the entire application though. |
@JoeMcB what's a minimal example of the problem? eg. the tests memoize the Lines 308 to 316 in 510cb57
|
@JoeMcB in addition to the minimal example, can you describe the problem? I'm not sure what you mean by |
Yep, that works fine! I actually submitted the PR for that feature. :) Our issue isn't calling flush on any memoized Class, it's needing to call flush on every memoized class. In our specific case, we're memoizing quite a few objects (at a class level) through our application. We've been adding a line
We've seen more than a few instances of a developer forgetting to add their newly memoized class into that spec configuration though. It'd be considerably easier from a testing perspective to have a The code posted above is working for us. I can wrap that in a PR if it'd be helpful for the base library. |
@JoeMcB be careful though, perhaps the code isn't clearing the cache when it should be. Maybe the tests are trying to demonstrate this? We have one mixin we use memoist for with many methods in ManageIQ, in our relationship mixin, which is included in many of our classes. We call If you notice, we call |
Sorry, that was a super complicated example but the point is to have one entrypoint to the memoization so you can easily clear the caching when you need to store a new value. |
Is there a way to globally flush the cache?
I have some nasty order dependent bugs in my rspecs where objects with their caches seem to be leaking from one spec to another.
So far, the best workaround I came up with is this
ObjectSpace.each_object { |o| o.flush_cache if o.respond_to? :flush_cache }
horrible workaround in my spec/spec_helper.rb.
Can we do better?
The text was updated successfully, but these errors were encountered: