IObjectModifiedEvent on Dexterity content and reindexing

I want to listen for this event, make a change to an attribute of that content object, and then reindex to update a column in the catalog. It is necessary that this occur after the object has been edited because I need to know the user that did it. The gotcha I have run into is that Dexterity uses the same event to reindex the content and mine seems to fire after this. So either my event listener would need to do a second reindex (bad) or not get changes updated in the catalog (also bad).

I've looked through the events provided by plone.dexterity such as EditFinishedEvent but that doesn't seem to achieve the results I want either. Is there an event I can listen for that occurs after content has been edited (or at least in a state where I can retrieve some data about it, even if it's not committed to the db yet) but before reindexing? Or perhaps I should look into overriding Dexterity's reindexOnModify event? (I don't actually know if that's possible!)

Just speculation, you could consider monkey patching any of following to set an annotation on the request object to de-dupe calls:

  1. Products.CMFCore.CMFCatalogAware.reindexObject(). This could have side-effects, if you are not careful.

  2. plone.dexterity.content.reindexOnModify() -- only would affect Dexterity content.

  3. Don't monkey patch and use a content class for your content that has its own reindexObject() method; this may be safest. Downside: you have to migrate content if you are using Item or Container as your base class (I've been burned too many times not having custom classes, for this very kind of reason).

It is a shame that order cannot be controlled in subscriber registration, but that is what it is.

Sean

In connection with the analysis related to

I found out that Plone (this has been Plone 4.2.4) has infrastructure (to be found in "collective.indexing") which optimizes indexing operations. These are not performed inline (immediately) but are queued for processing at the beginning of "transaction.commit". Before the actual processing, the queue indexing requests are optimized (avoiding duplicate indexing operations).

Thus, if those optimizations are active in your Plone installation for the objects your are interested in, you may not need to worry about a second "reindexObject" request.

1 Like

I came up with a solution that involves a limited amount of monkey patching. First of all, this is intended as a Dexterity behavior so it's fine that it only affects Dexterity content. DexterityContent subclasses Products.CMFCore.CMFCatalogAware.CatalogAware (among others) which is where reindexObject is defined. I see that it first calls notifyModified on the content and indeed Dexterity's base class uses this method to update the modified date and add a creator. I don't know of a way to update this with a behavior so I created a new event and monkey patched notifyModified to fire that event.

def notifyModified(self):
    self.addCreator()
    self.setModificationDate()
    notify(EditPreIndexEvent(self))

Then it was just a matter of creating a listener for this new event.