Hi,

On 2015-02-26, 11:40 PM, "OC" wrote:

Chuck,

On 27. 2. 2015, at 5:39, Chuck Hill 
<ch...@gevityinc.com<mailto:ch...@gevityinc.com>> wrote:

You?  A weird problem?  I am SHOCKED!  :-)

:)

I've noticed lately that my background tasks (each of which uses its own EC) 
stopped to delete old objects. Pursuing the culprit, I have found that it began 
when I (by Ramsey's advice) stopped moving objects betwixt those ECs using 
localInstanceIn,
Why was that?

Why was what? That I originally used localInstanceIn? For the task uses own EC, 
different from the default one. That I switched to GIDs? For Ramsey knows EOF 
much better than me, and

===
On Jan 29, 2015, at 9:41 AM, OC <o...@ocs.cz<mailto:o...@ocs.cz>> wrote:
  static ERXLongResponseTask csvTask(EOEnterpriseObject ownerEO) {
      ERXEC ec=ERXEC.newEditingContext()
      ec.lock() // do I really need to lock here?
      try {
          ownerEO=ownerEO.localInstanceIn(ec)
      } finally {
          ec.unlock()
      }
      def task=new ImportCSVTask(ownerEO:ownerEO)
      task.start()
      task
  }

On 29. 1. 2015, at 18:00, Ramsey Gurley 
<rgur...@smarthealth.com<mailto:rgur...@smarthealth.com>> wrote:

You can't pass EOs to a background thread. You need to pass EOGlobalIDs to your 
runnable constructor instead and then create your new ec on the background 
thread when you begin processing. Your constructor is passing full EOs and thus 
you are getting weird behavior.

You can pass in EOs *if* you don't keep a reference to them (e.g. If you just 
localInstance them and then discard the reference before the thread runs as you 
are doing).  Holding references is  problem as then two threads can cause 
changes, get hung up on locks etc.  Passing in the global ID is safer as you 
can never do it wrong.

For the rest of the problem below, I am just shaking my head in amazement.  Do 
you have any validateForDelete methods in your code?

Chuck



On 29. 1. 2015, at 19:05, Ramsey Gurley 
<rgur...@smarthealth.com<mailto:rgur...@smarthealth.com>> wrote:

You should do something like
ERXLongResponse csvTask(ERXGenericRecord eo) {
EOGlobalID gid = eo.permanentGlobalID();
ImportCSVTask task = new ImportCSVTask(gid);
...
}
class ImportCSVTask {
private EOGlobalID _gid;
ImportCSVTask(EOGlobalID gid) {
_gid = gid;
}
performAction() {
//Safe here. Method called by the background thread
EOEditingContext ec = ERXEC.newEditingContext();
EOEnterpriseObject eo = ERXEOGlobalIDUtilities.fetchObjectWithGlobalID(ec, 
_gid);
//Do stuff
}
}
You grab the gid, pass it to the runner, then when the background thread calls 
run() on the runner, return the gid to an eo. Use wonder classes to do this 
like the ERXLongResponseTask mentioned or an ERXRunnable since those do the 
auto locking magic for you.

===

Now, is that wrong? I am now using that approach, and my only digress is using 
faultForGlobalID instead of ERXEOGlobalIDUtilities.fetchObjectWithGlobalID.

I am able to repeat the problem e.g., this way:
=== launched very early in Application, no session/component created yet ===
  def ec=ERXEC.newEditingContext()
  def auction=EOUtilities.objectWithPrimaryKeyValue(ec,'DBAuction',1000003)
  def records=auction.importedRecords()
  println "owning rel: 
${auction.ownsDestinationObjectsForRelationshipKey('importedRecords')} inverse 
'${auction.inverseForRelationshipKey('importedRecords')}' #$records.count" // 
just to make sure it's all right
  def lr=records.lastObject()
  println "-- in 'default' EC removing $lr from $auction..."
  lr.removeObjectFromBothSidesOfRelationshipWithKey(auction,'auction')
  auction.editingContext().saveChanges() // my delegate logs out all adaptor 
ops: this does delete all right
  def ec2=ERXEC.newEditingContext(new EOObjectStoreCoordinator())
  auction=ec2.faultForGlobalID(auction.permanentGlobalID(),ec2) // this is how 
I 'move' objects to background tasks...
  lr=ec2.faultForGlobalID(records.lastObject().permanentGlobalID(),ec2) // ... 
is it indeed the right way?
  println "-- in EC in extra OSC removing $lr from $auction..."
  lr.removeObjectFromBothSidesOfRelationshipWithKey(auction,'auction')
  auction.editingContext().saveChanges() // for this one DOES NOT delete, see 
the logs below!
===
This code -- along with the logs in databaseContextWillPerformAdaptorOperations 
-- prints out this:
===
owning rel: true inverse 'auction' #2
-- in 'default' EC removing <DBRecord@1532707037 PK:1004656 /EC:829232957> from 
<DBAuction@357286753 PK:1000003 /EC:829232957>...
- 1: DELETE on 'DBRecord' (uid = 1004656)
-- in EC in extra OSC removing <DBRecord@2038388710 PK:1004657 /EC:489384291> 
from <DBAuction@325329592 PK:1000003 /EC:489384291>...
- 1: UPDATE on 'DBRecord' (uid = 1004657) 
1{auction_id:<com.webobjects.foundation.NSKeyValueCoding$Null>}
===
Does it make any sense?

It is already removed, so it does not remove it again?

There were two objects in the auction.importedRecords relationship. First, I've 
removed records.lastObject, the one with PK:1004656. Since it was removed, 
records.lastObject was the remaining one, the one with PK:1004657.

The same code -- but in another EC -- though did not remove it, though the 
relatioship is still owning...

Thanks a lot,
OC


_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      
(Webobjects-dev@lists.apple.com<mailto:Webobjects-dev@lists.apple.com>)
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/webobjects-dev/chill%40gevityinc.com

This email sent to ch...@gevityinc.com<mailto:ch...@gevityinc.com>
 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to