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 sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to