source: main/waeup.kofa/branches/uli-fix-zc-async/src/waeup/kofa/meta.py @ 17688

Last change on this file since 17688 was 15769, checked in by uli, 5 years ago

Unregister broken event handler on startup.

The indexAdded handler of zope.catalog tries to index all objects in a ZODB
when a new catalog index is added. This means trouble with large catalogs and
we disable this handler on startup. Other ways to unregistering it are more
difficult.

  • Property svn:keywords set to Id
File size: 5.2 KB
Line 
1## $Id: meta.py 15769 2019-11-07 13:20:25Z uli $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""Grokkers for Kofa components.
19
20Stuff in here is mainly taken from grok.meta, with some modifications
21to provide a possibility to update catalogs in a running site. This is
22to solve the very common problem of already running sites for which
23the software changes and adds catalogs. These catalogs will not be
24automatically added in a running site.
25
26With the following Grokker and the upgrade helper class we can fire
27IObjectUpgradedEvents for any existing site and all catalogs
28registered will be really created.
29
30Please note that yet these catalogs are not filled automatically! That
31means the catalogs will exist but are empty in the beginning.
32
33We might solve this second problem by firing extra events like some
34ICatalogUpdatedEvent (which still do not exist) or similar.
35"""
36import grok
37import grokcore.component
38import martian
39from grok import components
40from grok.meta import IndexesSetupSubscriber
41from martian.error import GrokError
42from zope import component
43from zope.processlifetime import IDatabaseOpened
44from waeup.kofa.interfaces import IObjectUpgradeEvent
45
46class IndexesGrokker(martian.InstanceGrokker):
47    """Grokker for Grok index bundles."""
48    martian.component(components.IndexesClass)
49
50    def grok(self, name, factory, module_info, config, **kw):
51        site = grok.site.bind().get(factory)
52        context = grok.context.bind().get(factory, module_info.getModule())
53        catalog_name = grok.name.bind().get(factory)
54
55        if site is None:
56            raise GrokError("No site specified for grok.Indexes "
57                            "subclass in module %r. "
58                            "Use grok.site() to specify."
59                            % module_info.getModule(),
60                            factory)
61        indexes = getattr(factory, '__grok_indexes__', None)
62        if indexes is None:
63            return False
64
65        subscriber = KofaIndexesUpgradeSubscriber(
66            catalog_name, indexes, context, module_info)
67        subscribed = (site, IObjectUpgradeEvent)
68        config.action(
69            discriminator=None,
70            callable=component.provideHandler,
71            args=(subscriber, subscribed),
72            )
73        return True
74
75
76class KofaIndexesUpgradeSubscriber(IndexesSetupSubscriber):
77    """Helper that sets up indexes when their Grok site is upgraded.
78
79    Each `grok.Indexes` class serves as an assertion that, whenever an
80    instance of its `grok.site()` is upgraded, the given list of
81    indexes should be generated if not already created as well.  But a
82    long period of time could elapse between when the application
83    starts (and its indexes are grokked), and the moment, maybe days
84    or weeks later, when a new instance of that `grok.Site` is
85    created.  Hence this `IndexesSetupSubscriber`: it can be
86    instantiated at grokking time with the index information, and then
87    registered with the Component Architecture as an event that should
88    be fired later, whenever the right kind of `grok.Site` is
89    instantiated.  At that point its `__call__` method is kicked off
90    and it makes sure the index catalogs get created properly.
91
92    """
93    def __call__(self, site, event):
94        #site.logger.info('Create catalog `%s` if not installed yet.'  % (
95        #        self.catalog_name,))
96        # make sure we have an intids
97        self._createIntIds(site)
98        # get the catalog
99        catalog = self._createCatalog(site)
100        # now install indexes
101        for name, index in self.indexes.items():
102            try:
103                #site.logger.info('Create index `%s` in catalog.' % name)
104                index.setup(catalog, name, self.context, self.module_info)
105                site.logger.info('%s: Index %s created.' % (self.catalog_name,name))
106            except KeyError: #, DuplicationError:
107                #site.logger.info('Index `%s` already in catalog.' % name)
108                pass
109        #site.logger.info('Catalog `%s` ready.' % self.catalog_name)
110
111
112
113@grokcore.component.subscribe(IDatabaseOpened)
114def disable_broken_handlers(event):
115    """This one is fired after ZODB setup.
116
117    Unregsiter handlers etc., that are broken or meant trouble in the past.
118    """
119    from zope.component import getGlobalSiteManager
120    from zope.catalog.catalog import indexAdded
121    worked = getGlobalSiteManager().unregisterHandler(indexAdded)
122    if worked:
123        print("Unregistered handler zope.catalog.catalog.indexAdded")
124    # TODO: register a replacement that copes better with large indexes.
Note: See TracBrowser for help on using the repository browser.