On Sep 27, 2012, at 1:28 AM, Michael Kowalchik wrote:
> Lets say I have object A that's in the cache and it has a relationship, A.B
> that was stored along with it in the cache. If I retrieve A from the cache I
> can get A.B and I get the cached copy of B. If B is modified, however, then
> my simple cache invalidator event handler doesn't see that B is cached (no
> __cached__ property on B) and B gets committed to the database without the
> cached copy of A being invalidated. Now subsequent cache hits of A will have
> a stale A.B relationship.
> So my question is, is there a clean / simple way to mark A for invalidation
> when B is modified? I've come up with a few schemes but all of them seem
> brittle, complicated, and my intuition is telling me that I'm reinventing the
> wheel; that some facility in SQLAlchemy itself may be useful in walking this
> relationship graph to find loaded, connected relationships who's cached
> represenations might need to be invalidated. Alternatively, is there another
> pattern that would be better suited to this kind of object-level caching?
well you're checking __cached__ in an after_commit() hook. usually the
technique here if you want relationships is to *cascade* the operation at that
point. So assuming its OK that you'd be leading from A, when A is
__cached__, checking it for "dirty" also means you need to traverse down its
relationships. this is a straight ahead graph traversal problem, but you're
right SQLA obviously has this function built into it. you can use the
cascade_iterator() feature of mapper():
state = instance_state(myobject)
mapper = state.mapper
for related in mapper.cascade_iterator("save-update", state):
# do check
where above you're cascading along the "save-update" cascade setting which is
enabled on all relationships by default.
The other pattern might be, to drive from how you phrased it, "mark A for
invalidation when B is modified". That is, use event handlers so that when a
B is attached to an A, it gets associated in some way such that a change on B
propagates up to the A (which would mean more event handlers .... we dont as
yet have an event "any change on class X", they are all per-attribute. this
is more involved but could save you from lots of traversals in your
after_commit hook depending on the circumstances.
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.