[Erp5-report] r45644 jm - in /erp5/trunk/products/ERP5Type: ./ dynamic/ tests/

nobody at svn.erp5.org nobody at svn.erp5.org
Fri Apr 22 15:02:58 CEST 2011


Author: jm
Date: Fri Apr 22 15:02:58 2011
New Revision: 45644

URL: http://svn.erp5.org?rev=45644&view=rev
Log:
bootstrap: retry migration if previous transaction failed

Modified:
    erp5/trunk/products/ERP5Type/TransactionalVariable.py
    erp5/trunk/products/ERP5Type/dynamic/portal_type_class.py
    erp5/trunk/products/ERP5Type/tests/testERP5TypeInterfaces.py

Modified: erp5/trunk/products/ERP5Type/TransactionalVariable.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/TransactionalVariable.py?rev=45644&r1=45643&r2=45644&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/TransactionalVariable.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/TransactionalVariable.py [utf8] Fri Apr 22 15:02:58 2011
@@ -59,6 +59,8 @@ import warnings
 from UserDict import IterableUserDict
 from Shared.DC.ZRDB.TM import TM
 from threading import local
+import transaction.interfaces
+import zope.interface
 
 class TransactionalVariable(TM, IterableUserDict):
   """TransactionalVariable provides a dict-like look-n-feel.
@@ -97,3 +99,25 @@ def getTransactionalVariable(context=_MA
     tv = TransactionalVariable()
     transactional_variable_pool.instance = tv
     return tv
+
+
+class TransactionalResource(object):
+
+  zope.interface.implements(transaction.interfaces.IDataManager)
+
+  def __init__(self, transaction_manager=None, **kw):
+    if transaction_manager is None:
+      from transaction import manager as transaction_manager
+    self.__dict__.update(kw, transaction_manager=transaction_manager)
+    transaction_manager.get().join(self)
+
+  @classmethod
+  def registerOnce(cls, *args):
+    tv = getTransactionalVariable().setdefault(cls, set())
+    return not (args in tv or tv.add(args))
+
+  def sortKey(self):
+    return 1
+
+  abort = commit = tpc_vote = tpc_begin = tpc_finish = tpc_abort = \
+    lambda self, transaction: None

Modified: erp5/trunk/products/ERP5Type/dynamic/portal_type_class.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/dynamic/portal_type_class.py?rev=45644&r1=45643&r2=45644&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/dynamic/portal_type_class.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/dynamic/portal_type_class.py [utf8] Fri Apr 22 15:02:58 2011
@@ -40,6 +40,7 @@ from Products.ERP5Type.Utils import setD
 from Products.ERP5Type import document_class_registry, mixin_class_registry
 from Products.ERP5Type.dynamic.accessor_holder import AccessorHolderModuleType, \
     createAllAccessorHolderList
+from Products.ERP5Type.TransactionalVariable import TransactionalResource
 
 from zLOG import LOG, ERROR, INFO, WARNING
 
@@ -337,7 +338,11 @@ def synchronizeDynamicModules(context, f
 
   Base.aq_method_lock.acquire()
   try:
-    if portal.id not in _bootstrapped:
+    # Thanks to TransactionalResource, the '_bootstrapped' global variable
+    # is updated in a transactional way. Without it, it would be required to
+    # restart the instance if anything went wrong.
+    if portal.id not in _bootstrapped and \
+       TransactionalResource.registerOnce(__name__, 'bootstrap', portal.id):
       migrate = False
       from Products.ERP5Type.Tool.PropertySheetTool import PropertySheetTool
       from Products.ERP5Type.Tool.TypesTool import TypesTool
@@ -366,10 +371,12 @@ def synchronizeDynamicModules(context, f
         if PickleUpdater.get:
           portal.migrateToPortalTypeClass()
         portal.portal_skins.changeSkin(None)
+        TransactionalResource(tpc_finish=lambda txn:
+            _bootstrapped.add(portal.id))
         LOG('ERP5Site', INFO, 'Transition successful, please update your'
             ' business templates')
-
-      _bootstrapped.add(portal.id)
+      else:
+        _bootstrapped.add(portal.id)
 
     LOG("ERP5Type.dynamic", 0, "Resetting dynamic classes")
     try:

Modified: erp5/trunk/products/ERP5Type/tests/testERP5TypeInterfaces.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/tests/testERP5TypeInterfaces.py?rev=45644&r1=45643&r2=45644&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/tests/testERP5TypeInterfaces.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/tests/testERP5TypeInterfaces.py [utf8] Fri Apr 22 15:02:58 2011
@@ -54,6 +54,11 @@ implements_tuple_list = [
 class TestERP5TypeInterfaces(ERP5TypeTestCase):
   """Tests implementation of interfaces"""
 
+  def testTransactionalResource(self):
+    from Products.ERP5Type.TransactionalVariable import TransactionalResource
+    from transaction.interfaces import IDataManager
+    verifyClass(IDataManager, TransactionalResource)
+
 def makeTestMethod(import_tuple, interface):
   """Common method which checks if documents implements interface"""
   def testMethod(self):



More information about the Erp5-report mailing list