followup+workaround: saveChanges refaults relationships which target changed entities (was: way too many SELECTs?)
followup+workaround: saveChanges refaults relationships which target changed entities (was: way too many SELECTs?)
- Subject: followup+workaround: saveChanges refaults relationships which target changed entities (was: way too many SELECTs?)
- From: OC <email@hidden>
- Date: Sun, 15 Feb 2015 14:31:28 +0100
Well I got at least one idea -- to catch the EC invalidation delegate message (if called) and have a peek at the callstack who does the invalidation.
The delegate message does get called, and I'm none the smarter from the call stack -- it's the editing context all right, no code of mine involved. To be sure the invalidated object is one of the ones which should have survived, I've changed the "WEIRD 21" log to
===
println "WEIRD 21 fault: ${createdBy.priceOffers().isFault()} // first ${createdBy.priceOffers()[0]}"
===
and added an EC delegate which implements editingContextShouldInvalidateObject and prints out the invalidated object and the stacktrace, and now I am getting this:
===
WEIRD 21 fault: false // first <DBPriceOffer@36842692 PK:1000001 /EC:654082169>
SHOULD INVALIDATE EC:654082169 eo: <DBPriceOffer@36842692 PK:1000001 /EC:654082169>
at model.QUICKANDDIRTY.editingContextShouldInvalidateObject(DBPriceOffer.groovy:8)
at com.webobjects.foundation.NSSelector._safeInvokeMethod(NSSelector.java:122)
at com.webobjects.foundation._NSDelegate._perform(_NSDelegate.java:223)
at com.webobjects.foundation._NSDelegate.booleanPerform(_NSDelegate.java:187)
at com.webobjects.eocontrol.EOEditingContext._refaultObjectWithGlobalID(EOEditingContext.java:3255)
at com.webobjects.eocontrol.EOEditingContext._newChangesFromInvalidatingObjectsWithGlobalIDs(EOEditingContext.java:3485)
at com.webobjects.eocontrol.EOEditingContext._processObjectStoreChanges(EOEditingContext.java:3522)
at er.extensions.eof.ERXEC._processObjectStoreChanges(ERXEC.java:1569)
at com.webobjects.foundation.NSSelector.invoke(NSSelector.java:358)
at com.webobjects.foundation.NSSelector._safeInvokeSelector(NSSelector.java:110)
at com.webobjects.eocontrol.EOEditingContext._sendOrEnqueueNotification(EOEditingContext.java:4715)
at com.webobjects.eocontrol.EOEditingContext._objectsChangedInStore(EOEditingContext.java:3562)
at er.extensions.eof.ERXEC._objectsChangedInStore(ERXEC.java:1509)
at er.extensions.eof.ERXEC.processQueuedNotifications(ERXEC.java:1584)
at er.extensions.eof.ERXEC.saveChanges(ERXEC.java:1124)
at er.extensions.eof.ERXEC$saveChanges$5.call(Unknown Source)
at model.DBPriceOffer$_newOffer_closure1.doCall(DBPriceOffer.groovy:43) // which is my saveChanges at //* below
...
===
Has perhaps anyone the slightest idea why on earth the EOEditingContext might want to refault in _newChangesFromInvalidatingObjectsWithGlobalIDs?
Incidentally, it allows a work-around: if I use (for this particular saving only) a delegate which returns 'false' from the editingContextShouldInvalidateObject method, it works all right -- the relationships are not refaulted and nothing gets unnecessarily refetched, no superfluous round-trips. But darn, that should not be needed?!? :-O
Thanks a lot,
OC
On 15. 2. 2015, at 12:04, OC <email@hidden> wrote:
> Tried to add a couple of logs to the Database Context delegate methods.
>
> Looks like at the moment
>
> - when databaseContextWillPerformAdaptorOperations gets called, the relationship still lives (not fault)
> - when databaseContextDidFetchObjects gets called, the relationship has already been turned to a fault.
>
> Hm. Does it help any finding the culprit? Looks like I'm sort of outta ideas :/
>
> Thanks a lot,
> OC
>
> On 15. 2. 2015, at 11:41, OC <email@hidden> wrote:
>
>> Hello there,
>>
>> further investigating the problem with re-fetching already fetched objects, I have added some logs into the databaseContextShouldFetchObjects delegate method (thanks, Chuck, for indirectly pointing me there) and eventually found that whilst before saveChanges the objects are fetched all right, after it the priceOffers relationships have been refaulted. What the heck.
>>
>> Namely, with a code like this (the "others" relationships I've selected quite randomly just to see whether they stick or not)
>>
>> ===
>> 3.times {
>> DBPriceOffer o=new DBPriceOffer()
>> o.price=-1 // just a tag allowing to clean up the mess in the DB
>> createdBy.editingContext().insertObject(o)
>> println "WEIRD 17 newo: $o, creator: $createdBy // EC:${o.editingContext()} (FTS:${(System.currentTimeMillis()-o.editingContext().fetchTimestamp())/1000} s) fault: ${createdBy.priceOffers().isFault()} // others: ${createdBy.auditItems().isFault()} ${createdBy.formPrototype().isFault()} ${auction.createdBy().isFault()} ${auction.priceOffers().isFault()}"
>> o.addObjectToBothSidesOfRelationshipWithKey(createdBy,'user')
>> println "WEIRD 21 fault: ${createdBy.priceOffers().isFault()} // others: ${createdBy.auditItems().isFault()} ${createdBy.formPrototype().isFault()} ${auction.createdBy().isFault()} ${auction.priceOffers().isFault()}"
>> o.editingContext().saveChanges() //*
>> println "WEIRD 23 fault: ${createdBy.priceOffers().isFault()} // others: ${createdBy.auditItems().isFault()} ${createdBy.formPrototype().isFault()} ${auction.createdBy().isFault()} ${auction.priceOffers().isFault()}"
>> }
>> System.exit(0) // to keep the mess in DB limited
>> ===
>>
>> and delegate method
>>
>> ===
>> NSArray databaseContextShouldFetchObjects(EODatabaseContext dbCtxt, EOFetchSpecification fs, EOEditingContext ec) {
>> if (fs.entityName=='DBPriceOffer' && (fs.qualifier in EOKeyValueQualifier) && fs.qualifier.key=='user') {
>> println "/DCSFO/ want POs of USER $fs.qualifier.value"
>> println "/DCSFO/ -> whose POs are fault: ${fs.qualifier.value.priceOffers.isFault()}"
>> }
>> return null
>> }
>> ===
>>
>> I am getting this -- I have added **'s to the interesting values.
>>
>> Note please the auction's priceOffers, which are NOT updated -- the real code of course contains "o.addObjectToBothSidesOfRelationshipWithKey(auction,'auction')", but I've removed it from the test code to keep it as plain as possible -- get re-faulted too (and stay this way, for, unlike the relationship of the user, it is not touched and thus fired; user's relationship is touched -- and fired -- each time):
>>
>> ===
>> WEIRD 17 newo: <DBPriceOffer@747124234 PK:null N /EC:991824826>, creator: <DBUser@841551067 PK:1000008 Name:'cl' T:'5' /EC:991824826> // EC:er.extensions.eof.ERXEC@3b1e0bba (FTS:3640.327 s) fault: true // others: true false true false
>> /DCSFO/ want POs of USER <DBUser@841551067 PK:1000008 Name:'cl' T:'5' /EC:991824826>
>> /DCSFO/ -> whose POs are fault: true
>> WEIRD 21 fault: *false* // others: true false true *false*
>> WEIRD 23 fault: *true* // others: true false true *true*
>>
>> WEIRD 17 newo: <DBPriceOffer@869533795 PK:null N /EC:991824826>, creator: <DBUser@841551067 PK:1000008 Name:'cl' T:'5' /EC:991824826> // EC:er.extensions.eof.ERXEC@3b1e0bba (FTS:3641.102 s) fault: true // others: true false true true
>> /DCSFO/ want POs of USER <DBUser@841551067 PK:1000008 Name:'cl' T:'5' /EC:991824826>
>> /DCSFO/ -> whose POs are fault: true
>> WEIRD 21 fault: *false* // others: true false true true
>> WEIRD 23 fault: *true* // others: true false true true
>>
>> WEIRD 17 newo: <DBPriceOffer@506662331 PK:null N /EC:991824826>, creator: <DBUser@841551067 PK:1000008 Name:'cl' T:'5' /EC:991824826> // EC:er.extensions.eof.ERXEC@3b1e0bba (FTS:3641.375 s) fault: true // others: true false true true
>> /DCSFO/ want POs of USER <DBUser@841551067 PK:1000008 Name:'cl' T:'5' /EC:991824826>
>> /DCSFO/ -> whose POs are fault: true
>> WEIRD 21 fault: *false* // others: true false true true
>> WEIRD 23 fault: *true* // others: true false true true
>> APPLICATION SHUTDOWN SEQUENCE COMPLETE
>> ===
>>
>> The question is -- how can this happen?
>>
>> Might I be forgetting of some code of mine which gets called as a side-effect of saveChanges and does this?
>>
>> Neither validateForSave nor my other database context delegate methods are the culprit: I've out-commented them, run the app, and without them it behaves precisely the same way.
>>
>> What else might cause this?!?
>>
>> Thanks,
>> OC
>>
>>
>> _______________________________________________
>> 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
>
>
> _______________________________________________
> 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
_______________________________________________
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