impossible for cache plugin authors to know the state of @value since the object is either contructed via Entry.new, where @value will be nil or Marshal.dump'd
https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/cache.rb#L561
or maybe the object was created this way
https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/cache.rb#L541
however, the accessor will go boom if the second way is chosen, since it handles only nil or marshaled values
https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/cache.rb#L587
so this is broken, but it's also slow since implementations of 'read_entry' will always cause a Marshal.dump to occur if they don't subvert the contructor with .create - but using .create results in broken entries since #value assumes marshal'd... ;-/
pretty close. since we can call either
Entry.new(object, :compress => true)
and hit the marshaling code, or not
Entry.new(object)
the issues with this are
- it's really a terrible signature: having :compress imply marshal is weird
- it's inverted, we need to know all possible calls to Entry.new to know if people are inadvertently passing in :compress or not... there is a lot of currying in the cache code so this is definitely possible.
i think the rails3 concept of having two discerte factories is the correct one since, logically, we are either creating an entry and preparing to be written to cache or loading one from cache. so two approaches suggest themselves
add back Entry.create, something like
def Entry.create(object, *args, &block)
warn 'never pass extract arguments to .create' unless args.empty?
allocate.tap do |entry|
entry.instance_eval do
@v = object
@c = false
end
end
end
this is ok but the signatures
Entry.create
Entry.new
seem entirely inverted to me. as in .create in ruby-land would normally be saving whereas new would not.
maybe naming would help
def Entry.for_write(object, created_at, options = {})
end
def Entry.for_read(key)
end
but rails doesn't take this approach much - it seems to think .new is the best...
maybe some sort of callback/hook that's called to compress/marshal entries at the last moment...
def before_cache
@v = serialize(@v)
end
icky.
and the end of the day i'd probably take the absolute simplest path: never automagically compress / marshal objects in the base Entry class and, instead, leave that up to Store authors defining 'read_entry' and 'write_entry'. that, however, is a major breaking change and i'm not sure what the rules for rails4 and api signatures are...
thoughts?
π π π π π π π π