From b983973899c875f297b2f07b4b65c22c09757d3f Mon Sep 17 00:00:00 2001
From: Arnaud Fontaine <arnaud.fontaine@nexedi.com>
Date: Wed, 18 Jan 2012 18:53:58 +0900
Subject: [PATCH] Make sure that erp5.component modules are reset on all ZEO
 clients.

---
 product/ERP5Type/Tool/ComponentTool.py      | 11 +++++---
 product/ERP5Type/dynamic/component_class.py | 29 ++++++++++++++++++++-
 product/ERP5Type/dynamic/dynamic_module.py  |  5 ++--
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/product/ERP5Type/Tool/ComponentTool.py b/product/ERP5Type/Tool/ComponentTool.py
index af298face9..37eccc766a 100644
--- a/product/ERP5Type/Tool/ComponentTool.py
+++ b/product/ERP5Type/Tool/ComponentTool.py
@@ -46,14 +46,19 @@ class ComponentTool(BaseTool):
   security = ClassSecurityInfo()
   security.declareObjectProtected(Permissions.AccessContentsInformation)
 
-  def reset(self):
+  def reset(self, is_sync=False):
     """
     XXX-arnau: global reset
     """
     import erp5.component
 
-    container_type_info = self.getPortalObject().portal_types.getTypeInfo(
-      self.getPortalType())
+    portal = self.getPortalObject()
+
+    if not is_sync:
+      portal.newCacheCookie('component_classes')
+      erp5.component._last_reset = portal.getCacheCookie('component_classes')
+
+    container_type_info = portal.portal_types.getTypeInfo(self.getPortalType())
 
     for content_type in container_type_info.getTypeAllowedContentTypeList():
       module_name = content_type.split(' ')[0].lower()
diff --git a/product/ERP5Type/dynamic/component_class.py b/product/ERP5Type/dynamic/component_class.py
index 76e4df0f84..0e6a638d98 100644
--- a/product/ERP5Type/dynamic/component_class.py
+++ b/product/ERP5Type/dynamic/component_class.py
@@ -26,12 +26,39 @@
 #
 ##############################################################################
 
+from Products.ERP5.ERP5Site import getSite
+from types import ModuleType
+
+class ComponentModule(ModuleType):
+  _resetting = False
+  _last_reset = -1
+
+  def __getattribute__(self, name):
+    """
+    Synchronize between ZEO clients
+
+    XXX-arnau: surely bad from a performance POV and not thread-safe
+    """
+    if name[0] == '_' or self._resetting:
+      return super(ComponentModule, self).__getattribute__(name)
+
+    import erp5.component
+    site = getSite()
+    cookie = site.getCacheCookie('component_classes')
+    if self._last_reset == -1:
+      self._last_reset = site.getCacheCookie('component_classes')
+    elif cookie != self._last_reset:
+      self._resetting = True
+      site.portal_components.reset(is_sync=True)
+      self._resetting = False
+
+    return super(ComponentModule, self).__getattribute__(name)
+
 from types import ModuleType
 from zLOG import LOG, INFO
 
 def generateComponentClassWrapper(namespace):
   def generateComponentClass(component_name):
-    from Products.ERP5.ERP5Site import getSite
     site = getSite()
 
     component_id = '%s.%s' % (namespace, component_name)
diff --git a/product/ERP5Type/dynamic/dynamic_module.py b/product/ERP5Type/dynamic/dynamic_module.py
index 9cbad41b80..9b3f836c90 100644
--- a/product/ERP5Type/dynamic/dynamic_module.py
+++ b/product/ERP5Type/dynamic/dynamic_module.py
@@ -122,10 +122,11 @@ def initializeDynamicModules():
                                                 loadTempPortalTypeClass)
 
   # Components
-  erp5.component = ModuleType("erp5.component")
+  from component_class import ComponentModule, generateComponentClassWrapper
+
+  erp5.component = ComponentModule("erp5.component")
   sys.modules["erp5.component"] = erp5.component
 
-  from component_class import generateComponentClassWrapper
   erp5.component.extension = registerDynamicModule(
     'erp5.component.extension',
     generateComponentClassWrapper('erp5.component.extension'))
-- 
2.30.9