Re: too many database conflicts when using ZODB with int ids and indexes
Jason Madden <[email protected]>
| Newsgroups | gmane.comp.web.zope.zodb |
|---|---|
| Message-ID | <[email protected]> |
> On Nov 18, 2016, at 05:34, Jim Fulton <[email protected]> wrote: > >> If i use ZC.intid in place of zope.intId then how to get rid of these subscribers in zope.intid ? You guys must have done this. >> >> >> <subscriber handler=".removeIntIdSubscriber" /> >> <subscriber handler=".addIntIdSubscriber" /> >> >> both the handlers are assuming that KeyReference based int id being used. and call getId of ZC.intId by passing a KeyReference object. KeyReference object is a wrapper object containing original object as an attribute > > You have to replace them with subscribers that behave differently. While you *could* instead register a more specific IKeyReference adapter for your objects that just returns the object, I don't think that's a particularly good idea. The default KeyReferenceToPersistent has its uses. Here's how my group configures zc.intid: <!-- configure.zcml --> <!-- If we load zope.intid, we get subscribers for the Object events that ensure all ILocation objects are registered/unregistered when they are added/removed, plus another set of events when they get/lose intids. This second set of events is meant to update zope.catalog. A consequence of this is that ILocation objects must be adaptable to KeyReferences when they are ObjectAdded (for purposes of zope.intid, which we don't care about, but this also ensures that they have ZODB Connections, which is good). We cannot use these subscribers as-is due to the way the use IKeyReference and try to register that. However, our subscribers *do* make sure that the given objects can be adapted to IKeyReference because that's useful and may be required by catalogs or other subscribers. --> <exclude package="zope.intid" file="subscribers.zcml" /> <include package="zope.intid" /> <include package="zope.keyreference" /> <!-- zc.intid fires a different set of events when objects gain/lose intids. --> <include package="zc.intid" /> <!-- This file has a bug (uses 'interface' instead of 'implements'), so we replicate its effect manually. --> <!-- <include package="zc.intid" file="zope-intid.zcml" /> --> <class class="zc.intid.utility.IntIds"> <implements interface="zope.intid.interfaces.IIntIds"/> </class> <subscriber handler=".subscribers.intIdEventNotify" /> <subscriber handler=".subscribers.addIntIdSubscriber" /> <subscriber handler=".subscribers.removeIntIdSubscriber" /> <subscriber handler=".subscribers.nti_intIdEventNotify" /> I'll be fixing the bug in zc.intid's zope-intid.zcml. Here's what the subscribers.py looks like for us: def _utilities_and_key(ob): utilities = tuple(component.getAllUtilitiesRegisteredFor(IIntIds)) return utilities, IKeyReference(ob, None) if utilities else None # Don't even bother trying to adapt if no utilities @adapter(ILocation, IObjectAddedEvent) def addintIdSubscriber(ob, event): """ Registers the object in all unique id utilities and fires an event for the catalogs. Notice that each utility will fire :class:`zc.intid.interfaces.IIntIdAddedEvent`; this subscriber will then fire one single :class:`zope.intid.interfaces.IIntIdAddedEvent`, followed by one single :class:`nti.intid.interfaces.IIntIdAddedEvent`; this gives a guaranteed order such that :mod:`zope.catalog` and other Zope event listeners will have fired. """ utilities, key = _utilities_and_key(ob) if not utilities or key is None: return idmap = {} for utility in utilities: idmap[utility] = utility.register(ob) # Notify the catalogs that this object was added. notify(ZOPEIntIdAddedEvent(ob, event, idmap)) notify(NTIIntIdAddedEvent(ob, event, idmap)) @adapter(ILocation, IObjectRemovedEvent) def removeIntidSubscriber(ob, event): """ Removes the unique ids registered for the object in all the unique id utilities. Just before this happens (for the first time), an :class:`nti.intid.interfaces.IIntIdRemovedEvent` is fired, followed by an :class:`zope.intid.interfaces.IIntIdRemovedEvent`. Notice that this is fired before the id is actually removed from any utility, giving other subscribers time to do their cleanup. Before each utility removes its registration, it will fire :class:`zc.intid.interfaces.IIntIdRemovedEvent`. This gives a guaranteed order such that :mod:`zope.catalog` and other Zope event listeners will have fired. """ utilities, key = _utilities_and_key(ob) if not utilities or key is None: return # Notify the catalogs that this object is about to be removed, # if we actually find something to remove fired_event = False for utility in utilities: if not fired_event and utility.queryId(ob) is not None: fired_event = True notify(NTIIntIdRemovedEvent(ob, event)) notify(ZOPEIntIdRemovedEvent(ob, event)) try: utility.unregister(ob) except KeyError: pass @component.adapter(zope.intid.interfaces.IIntIdEvent) def intIdEventNotify(event): """ Event subscriber to dispatch IntIdEvent to interested adapters. """ handle(event.object, event) @component.adapter(nti.intid.interfaces.IIntIdEvent) def nti_intIdEventNotify(event): """ Event subscriber to dispatch IntIdEvent to interested adapters. """ handle(event.object, event) They're pretty simple, but maybe worth adding to zc.intid. -- You received this message because you are subscribed to the Google Groups "zodb" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.