On Aug 27, 2009, at 2:45 PM, Bob Morley wrote:
Today I spent some time figuring out why our entity list cache was not
working as expected. We had a PartyContent entity that was fetched
in a
entity-and with use-cache="true". However, when the PartyContent was
updated the cache was not properly flushed in the EntityList cache.
Here is
what I found:
1) Cache.remove(GenericEntity entity) is being called with the updated
GenericEntity. This is used to call
entityListCache.storeHook(entity, null)
and the signature expects to have oldvalue, newvalue. Ultimately it
iterates through the conditions and attempts to programatically
apply them
to the "old value". If there is match that condition is removed
from the
cache. The trouble of course, is that it is using the new value
which may
cause the condition to no longer match (as in our case).
2) During the comparison logic for the condition (above) the system
ultimately gets down to
EntityJoinOperator.entityMatches(GenericEntity, lhs,
rhs). This object has a "shortCircuitValue" (basically when should
I stop
checking for this condition). For our AND the short circuit value
would be
"false" as in if I hit false on the left-hand-side there is no point
in
checking the right-hand-side, lets leave now with FALSE. The
trouble was
the code looked like:
if (lhs.entityMatches(entity)) return shortCircuitValue;
instead of
if (lhs.entityMatches(entity) == shortCircuitValue) return
shortCircuitValue;
This pattern is in a few places, it was just wrong in this method and
mapMatches method (right below).
SO, I have a clear fix for #2 but my solution for #1 isn't great (I
go fetch
the entity from the database so I can get the "old value"). I would
like to
talk with someone with lots of caching experience here to make sure
I am not
off base. Also, wonder if there is a way to get the original
version of the
GenericEntity without doing a re-fetch. I was considering an
solution where
the fields would be changed to a MapStack where the updated fields
would be
on the top of the stack (always a stack of 2).
Thoughts?
The GenericEntity object keeps a Map with original values if it was
loaded from the database and then changed, so you should be able to
use that (it does seem weird that it isn't used already!).
-David