[Erp5-report] r42257 jm - in /erp5/trunk/products/CMFActivity: ./ Activity/ tests/
nobody at svn.erp5.org
nobody at svn.erp5.org
Wed Jan 12 12:39:10 CET 2011
Author: jm
Date: Wed Jan 12 12:39:10 2011
New Revision: 42257
URL: http://svn.erp5.org?rev=42257&view=rev
Log:
CMFActivity: allow activating an object from a before commit hook
This is required for workflow scripts that are run at the end of the transaction.
Modified:
erp5/trunk/products/CMFActivity/Activity/Queue.py
erp5/trunk/products/CMFActivity/ActivityBuffer.py
erp5/trunk/products/CMFActivity/ActivityTool.py
erp5/trunk/products/CMFActivity/tests/testCMFActivity.py
Modified: erp5/trunk/products/CMFActivity/Activity/Queue.py
URL: http://svn.erp5.org/erp5/trunk/products/CMFActivity/Activity/Queue.py?rev=42257&r1=42256&r2=42257&view=diff
==============================================================================
--- erp5/trunk/products/CMFActivity/Activity/Queue.py [utf8] (original)
+++ erp5/trunk/products/CMFActivity/Activity/Queue.py [utf8] Wed Jan 12 12:39:10 2011
@@ -273,7 +273,7 @@ class Queue:
return 0
# Transaction Management
- def prepareQueueMessage(self, activity_tool, m):
+ def prepareQueueMessageList(self, activity_tool, message_list):
# Called to prepare transaction commit for queued messages
pass
Modified: erp5/trunk/products/CMFActivity/ActivityBuffer.py
URL: http://svn.erp5.org/erp5/trunk/products/CMFActivity/ActivityBuffer.py?rev=42257&r1=42256&r2=42257&view=diff
==============================================================================
--- erp5/trunk/products/CMFActivity/ActivityBuffer.py [utf8] (original)
+++ erp5/trunk/products/CMFActivity/ActivityBuffer.py [utf8] Wed Jan 12 12:39:10 2011
@@ -33,108 +33,81 @@ class ActivityBuffer(TM):
_p_oid=_p_changed=_registered=None
- def __init__(self, activity_tool=None):
- self.requires_prepare = 0
-
- def _getBuffer(self):
- buffer = self
- # Create attributes only if they are not present.
- if not hasattr(buffer, 'queued_activity'):
- buffer.queued_activity = []
- buffer.flushed_activity = []
- buffer.message_list_dict = {}
- buffer.uid_set_dict = {}
- return buffer
-
- def _clearBuffer(self):
- buffer = self._getBuffer()
- del buffer.queued_activity[:]
- del buffer.flushed_activity[:]
- buffer.message_list_dict.clear()
- buffer.uid_set_dict.clear()
+ def __init__(self):
+ self.queued_activity = []
+ self.flushed_activity = []
+ self.message_list_dict = {}
+ self.uid_set_dict = {}
+
+ def _clear(self):
+ del self.queued_activity[:]
+ del self.flushed_activity[:]
+ self.message_list_dict.clear()
+ self.uid_set_dict.clear()
+ self.activity_tool = None
def getMessageList(self, activity):
- buffer = self._getBuffer()
- return buffer.message_list_dict.setdefault(activity, [])
+ return self.message_list_dict.setdefault(activity, [])
def getUidSet(self, activity):
- buffer = self._getBuffer()
- return buffer.uid_set_dict.setdefault(activity, set())
+ return self.uid_set_dict.setdefault(activity, set())
def _register(self, activity_tool):
if not self._registered:
- self._beginAndHook(activity_tool)
+ self.activity_tool = activity_tool
+ self._activity_tool_path = activity_tool.getPhysicalPath()
TM._register(self)
+ self._prepare_args = 0, 0
+ if self._prepare_args:
+ transaction.get().addBeforeCommitHook(self._prepare, self._prepare_args)
+ self._prepare_args = None
# Keeps a list of messages to add and remove
# at end of transaction
- def _beginAndHook(self, activity_tool):
+ def _begin(self):
# LOG('ActivityBuffer', 0, '_begin %r' % (self,))
from ActivityTool import activity_dict
- self.requires_prepare = 1
try:
-
# Reset registration for each transaction.
for activity in activity_dict.itervalues():
activity.registerActivityBuffer(self)
-
- # Notice: The operation below cannot fail silently, or we get errors late
- # in the transaction that are very hard to understand.
- transaction.get().addBeforeCommitHook(self.tpc_prepare,
- (transaction,),
- dict(activity_tool=activity_tool))
except:
LOG('ActivityBuffer', ERROR, "exception during _begin",
error=sys.exc_info())
raise
- def _finish(self, *ignored):
+ def _finish(self):
# LOG('ActivityBuffer', 0, '_finish %r' % (self,))
try:
try:
# Try to push / delete all messages
- buffer = self._getBuffer()
- for (activity, message) in buffer.flushed_activity:
+ for activity, message in self.flushed_activity:
activity.finishDeleteMessage(self._activity_tool_path, message)
- for (activity, message) in buffer.queued_activity:
+ for activity, message in self.queued_activity:
activity.finishQueueMessage(self._activity_tool_path, message)
except:
LOG('ActivityBuffer', ERROR, "exception during _finish",
error=sys.exc_info())
raise
finally:
- self._clearBuffer()
-
- def _abort(self, *ignored):
- self._clearBuffer()
-
- def tpc_prepare(self, transaction, sub=None, activity_tool=None):
- assert activity_tool is not None
- self._activity_tool_path = activity_tool.getPhysicalPath()
- # Do nothing if it is a subtransaction
- if sub is not None:
- return
+ self._clear()
- if not self.requires_prepare:
- return
+ _abort = _clear
- self.requires_prepare = 0
+ def _prepare(self, flushed, queued):
try:
+ activity_tool = self.activity_tool
# Try to push / delete all messages
- buffer = self._getBuffer()
- for (activity, message) in buffer.flushed_activity:
+ for activity, message in self.flushed_activity[flushed:]:
activity.prepareDeleteMessage(activity_tool, message)
activity_dict = {}
- for (activity, message) in buffer.queued_activity:
+ for activity, message in self.queued_activity[queued:]:
activity_dict.setdefault(activity, []).append(message)
for activity, message_list in activity_dict.iteritems():
- if hasattr(activity, 'prepareQueueMessageList'):
- activity.prepareQueueMessageList(activity_tool, message_list)
- else:
- for message in message_list:
- activity.prepareQueueMessage(activity_tool, message)
+ activity.prepareQueueMessageList(activity_tool, message_list)
+ self._prepare_args = len(self.flushed_activity), len(self.queued_activity)
except:
- LOG('ActivityBuffer', ERROR, "exception during tpc_prepare",
+ LOG('ActivityBuffer', ERROR, "exception during _prepare",
error=sys.exc_info())
raise
@@ -143,16 +116,14 @@ class ActivityBuffer(TM):
# Activity is called to prevent queuing some messages (useful for example
# to prevent reindexing objects multiple times)
if not activity.isMessageRegistered(self, activity_tool, message):
- buffer = self._getBuffer()
- buffer.queued_activity.append((activity, message))
+ self.queued_activity.append((activity, message))
# We register queued messages so that we can
# unregister them
activity.registerMessage(self, activity_tool, message)
def deferredDeleteMessage(self, activity_tool, activity, message):
self._register(activity_tool)
- buffer = self._getBuffer()
- buffer.flushed_activity.append((activity, message))
+ self.flushed_activity.append((activity, message))
def sortKey(self, *ignored):
"""Activities must be finished before databases commit transactions."""
Modified: erp5/trunk/products/CMFActivity/ActivityTool.py
URL: http://svn.erp5.org/erp5/trunk/products/CMFActivity/ActivityTool.py?rev=42257&r1=42256&r2=42257&view=diff
==============================================================================
--- erp5/trunk/products/CMFActivity/ActivityTool.py [utf8] (original)
+++ erp5/trunk/products/CMFActivity/ActivityTool.py [utf8] Wed Jan 12 12:39:10 2011
@@ -1041,14 +1041,15 @@ class ActivityTool (Folder, UniqueObject
finally:
global_activity_buffer_lock.release()
thread_activity_buffer = global_activity_buffer[my_instance_key]
- if my_thread_key not in thread_activity_buffer:
+ try:
+ return thread_activity_buffer[my_thread_key]
+ except KeyError:
if create_if_not_found:
- buffer = ActivityBuffer(activity_tool=self)
+ buffer = ActivityBuffer()
else:
buffer = None
thread_activity_buffer[my_thread_key] = buffer
- activity_buffer = thread_activity_buffer[my_thread_key]
- return activity_buffer
+ return buffer
security.declarePrivate('activateObject')
def activateObject(self, object, activity, active_process, **kw):
Modified: erp5/trunk/products/CMFActivity/tests/testCMFActivity.py
URL: http://svn.erp5.org/erp5/trunk/products/CMFActivity/tests/testCMFActivity.py?rev=42257&r1=42256&r2=42257&view=diff
==============================================================================
--- erp5/trunk/products/CMFActivity/tests/testCMFActivity.py [utf8] (original)
+++ erp5/trunk/products/CMFActivity/tests/testCMFActivity.py [utf8] Wed Jan 12 12:39:10 2011
@@ -3832,6 +3832,19 @@ class TestCMFActivity(ERP5TypeTestCase,
finally:
del activity_tool.__class__.doSomething
+ def test_126_beforeCommitHook(self):
+ """
+ Check it is possible to activate an object from a before commit hook
+ """
+ def doSomething(person):
+ person.activate(activity='SQLDict')._setFirstName('John')
+ person.activate(activity='SQLQueue')._setLastName('Smith')
+ person = self.portal.person_module.newContent()
+ transaction.get().addBeforeCommitHook(doSomething, (person,))
+ transaction.commit()
+ self.tic()
+ self.assertEqual(person.getTitle(), 'John Smith')
+
def test_connection_migration(self):
"""
Make sure the cmf_activity_sql_connection is automatically migrated from
More information about the Erp5-report
mailing list