On 16. 2. 2015, at 9:52, OC <[email protected]> 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 protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com
This email sent to [email protected]