relationship value different in another EC (was: ordered and filtered fault efficiency)
relationship value different in another EC (was: ordered and filtered fault efficiency)
- Subject: relationship value different in another EC (was: ordered and filtered fault efficiency)
- From: OC <email@hidden>
- Date: Tue, 17 Feb 2015 14:00:22 +0100
On 16. 2. 2015, at 9:52, OC <email@hidden> wrote:
> Nevertheless with the last valid thing I already took your advice and modelled it -- I dodged changing the DB for I was lucky and I happened to have in my model one legacy unused INTEGER attribute, which I used for a FK -- and preliminarily, it seems to work excellently.
Alas, it does not when there are concurrent threads -- in that case, one of them can still contain the old value for the relationship, although I am locking the OSC :(
My current code looks essentially like this:
===
EOEditingContext ec=auction.editingContext()
EOObjectStore osc=ec.rootObjectStore()
osc.lock()
try {
println "OLD: $auction.lastValidPriceOffer()" // now a modelled :1 relationship, auction contains FK
DBPriceOffer po=... new offer created and inserted to EC ...
println "ENCACHED: $po"
auction.setLastValidPriceOffer(po)
ec.saveChanges()
} finally {
println "NEW: $auction.lastValidPriceOffer()"
ocs.unlock()
}
===
Now, I though this code is safe (single-instance, concurrent requests), but it is not. If the reqeusts come sequentially, it works perfectly, but with concurrent requests I am getting results like this
=== // WorkerThread5 and WorkerThread4 run concurrently
# WorkerThread5 happened to lock first; WorkerThread4 waits all right
13:07:42.163|WorkerThread5 --- OLD <DBPriceOffer@2072296340 PK:1002835 Price:'888' by:'vilklient' /EC:1192846461>
17.2 13:07:42: ENCACHED: <DBPriceOffer@892254365 PK:null N Price:'887' by:'vilklient3' /EC:1192846461> [1]
# ops logged in databaseContextWillPerformAdaptorOperations; note the new lastValidPriceOffer FK (1002836) _is_ stored properly in lvo_id (where it replaces the previous one, 1002835):
- 1: INSERT on 'DBPriceOffer' 6{validOffer:true, uid:1002836, auction_id:1000755, price:887, creationDate:2015-02-17 12:07:42 Etc/GMT, creator_id:1000121}
- 2: UPDATE on 'DBAuction' ((uid = 1000755) and (lvo_id = 1002835)) 1{lvo_id:1002836}
# and just before unlocking, in this thread, lastValidPriceOffer is all right
13:07:42.235|WorkerThread5 --- NEW <DBPriceOffer@892254365 PK:1002836 Price:'887' by:'vilklient3' /EC:1192846461>
# since WorkerThread5 did save all right and did unlock the OSC, WorkerThread4 starts -- and oops, it still has the wrong old value of lastValidPriceOffer! [2]
13:07:42.246|WorkerThread4 --- OLD: <DBPriceOffer@746572082 PK:1002835 Price:'888' by:'vilklient' /EC:1851717404> prc 888 au.cpc 888
# from now on, of course it's all wrong. Nevertheless it is interesting that the thread _does know_ the _new_ value of lvo_id (1002836), and thus saves the wrong offer! [3]
- 1: INSERT on 'DBPriceOffer' 6{validOffer:true, uid:1002837, auction_id:1000755, price:887, creationDate:2015-02-17 12:07:42 Etc/GMT, creator_id:1000049}
- 2: UPDATE on 'DBAuction' ((uid = 1000755) and (lvo_id = 1002836)) 1{lvo_id:1002837}
===
I must admit I am (just again) somewhat surprised.
I rather presumed saveChanges would make sure values of all EOs (including the relationships) in all ECs in the same instance with just one OSC are consistent, and thus I would at [2] get the right value of lastValidPriceOffer -- the one stored (in another thread) before at [1], and successfully saved there.
I considered there's a possibility I am wrong, and the EC's will not get synced properly, and I will still get the old value of lastValidPriceOffer at [2] -- but in that case I thought the auction itself in the same EC of the same thread would also contain the old FK value in its 'lvo_id', and since it is a locking attribute, I will get an optimistic locking fail, and the wrong value will not be saved at [3].
I must admit I can't really see how it is possible the disastrous combination of
- the auction contains the _new_ foreign key;
- at the same moment, the relationship returns the _old_ object?!?
Note that it looks like some caching issue, for the problem never happens when saving is not concurrent. If the first thread's R/R loop finishes before the latter ones' starts, the relationship is consistent with the foreign key.
Is this normal EOF behaviour, or does it indicate another weird problem in my app?
And even more important -- how to fix it? What am I to do at the start/end of the OSC-locked critical section, so as I am sure that the FK stored inside the object and the relationship modelled on it are consistent?
Thanks a big lot!
OC
=== The relationship definition in the model plist:
{
deleteRule = EODeleteRuleDeny;
destination = DBPriceOffer;
isToMany = N;
joinSemantic = EOInnerJoin;
joins = (
{
destinationAttribute = "uid";
sourceAttribute = lvo_id;
},
);
name = lastValidPriceOfferCache;
},
===
=== The code used to access the relationship:
public DBPriceOffer lastValidPriceOffer {
def cached=this.lastValidPriceOfferCache()
if (cached) return cached
... legacy code to search for it for old auctions ...
}
DBPriceOffer lastValidPriceOfferCache() {
storedValueForKey('lastValidPriceOfferCache')
}
===
_______________________________________________
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