Re: Getting information on updated n:m relationship
Re: Getting information on updated n:m relationship
- Subject: Re: Getting information on updated n:m relationship
- From: Mike Schrag <email@hidden>
- Date: Fri, 9 Mar 2007 16:44:18 -0500
What you describe here is the first implementation I made for Project
Wonder, actually. It gets really nasty. The problem is that you
have to also watch for updates, because if you change a to-one
relationship, it only results in an update notification. But
objectsChangedInStoreNotification doesn't provide enough information
to respond correctly. By the time it gets to you, the snapshot cache
is already updated, so you have no idea what the PREVIOUS value was
(because that notification only gives you array of GIDs). Without
the previous value, you can't invalidate the OLD inverse to-many
relationship that should no longer reference the object, you can only
invalidate the NEW inverse to-many relationship that newly references
it. Under extensive load testing, they got out of sync with this
method for me. Maybe you have some other clever tricks, though --
this is all walking a tightrope, and it's really easy to screw it up
(I did. A lot.).
I finally came to the conclusion that it's not EO change notification
that I want to do, it's snapshot cache change notification. At the
cache level (= EODatabase in EOF), you have the old value (previously
in cache) and the new value (incoming in the parameter) that you can
then compare and get all the data you need (to-many snapshots or
regular snapshots).
There are several complications to this, however. One is that you
can't just replace EODatabase. You can replace EODatabaseContext,
but there's no factory method to intercept EODatabase creation. It
turns out if you sacrifice one method of EODatabaseContext (which is
only used by an EOUtilities, and never called in any code I've seen
-- forceConnectionWithModel), you can (via some trickery) replace
EODatabase also (see ERXDatabase/ERXDatabaseContext for details).
The other is that snapshots are updated CONSTANTLY. I mean
CONSTANTLY. So much so that I wonder how much CPU time ends up going
into that -- I haven't profiled it yet. So then the trick becomes
weeding out what is a "real" cache updated and what is a bogus EOF-
just-wants-to-update-you-for-the-heck-of-it update. With some
ThreadLocals in ERXDatabaseContext, and because EOF has a big lock, I
was able to keep enough state around to know the path that was taken
to perform the cache change and send out notifications from there
(not NSNotifications -- it's a little more specialized than that).
I actually track changes a little more aggressively than I need right
now (and will probably back down from it). For instance, I track to-
many diffs. My intention was to send just the added and removed GIDs
across the wire to other OSC's, but without a shared transaction
counter across all the instances, it's impossible to order the
changes on the remote side, which means you have no assurance that
you're playing them back in the right order from the other
instances. Only doing invalidations still /potentially/ has this
problem in specific scenarios, but it is WAY less likely to be a
problem.
Anyway, regardless of which route you take, write load tests and run
them with more than 2 instances (some problems only arose when I had 3
+ instances). You should also grab
ERXEOAccessUtilities.verifySnapshots from Project Wonder. It goes
through your entire snapshot cache (to-many and regular) and verifies
the state of the cache against the database without causing the cache
to be touched. This was invaluable for finding bugs. My process was
to run 3+ instance concurrent load tests, then run a verify snapshots
(via a direct action) on each instance. If change notification is
working properly, this should not report any inconsistencies.
ms
On Mar 9, 2007, at 3:41 PM, Andrew Lindesay wrote:
Hello Mike;
Yes ... They are a pain. I recently had to fight this part of EOF to
get notifications of to-many changes for multicast notification. If
What I do is to listen out for the delete and insert notifications
on the target instances (using a queue server) and when an object
(B) was changed then I also look at the reverse to-many
relationships back into that objects's entity from (A), get the
specific instance of A using the GID constructed from the foreign
key in (B) and then drop snapshots for the relationship A--->B.
This is quite a recent block of work (I used to do quite domain-
specific change notification) and it is only used in staging-
testing at the present time. Any comments on this arrangement
would be of interest.
cheers.
___
Andrew Lindesay
www.lindesay.co.nz
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden