Commit aaff9486 authored by Yoshinori Okuji's avatar Yoshinori Okuji

Accept partial failures in invokeGroup.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@4016 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 90df54bc
...@@ -402,16 +402,17 @@ class ActivityTool (Folder, UniqueObject): ...@@ -402,16 +402,17 @@ class ActivityTool (Folder, UniqueObject):
for m in message_list: for m in message_list:
try: try:
obj = m.getObject(self) obj = m.getObject(self)
i = len(new_message_list) # This is an index of this message in new_message_list.
if m.hasExpandMethod(): if m.hasExpandMethod():
for obj in m.getObjectList(self): for subobj in m.getObjectList(self):
path = obj.getPath() path = subobj.getPath()
if path not in path_dict: if path not in path_dict:
path_dict[path] = None path_dict[path] = i
expanded_object_list.append(obj) expanded_object_list.append(subobj)
else: else:
path = obj.getPath() path = obj.getPath()
if path not in path_dict: if path not in path_dict:
path_dict[path] = None path_dict[path] = i
expanded_object_list.append(obj) expanded_object_list.append(obj)
object_list.append(obj) object_list.append(obj)
new_message_list.append(m) new_message_list.append(m)
...@@ -427,27 +428,43 @@ class ActivityTool (Folder, UniqueObject): ...@@ -427,27 +428,43 @@ class ActivityTool (Folder, UniqueObject):
method = self.unrestrictedTraverse(method_id) method = self.unrestrictedTraverse(method_id)
# FIXME: how to pass parameters? # FIXME: how to pass parameters?
# FIXME: how to apply security here? # FIXME: how to apply security here?
# NOTE: expanded_object_list must be set to failed objects by the callee.
# If it fully succeeds, expanded_object_list must be empty when returning.
result = method(expanded_object_list) result = method(expanded_object_list)
except ConflictError: except ConflictError:
raise raise
except: except:
# In this case, the group method completely failed.
for m in new_message_list: for m in new_message_list:
m.is_executed = 0 m.is_executed = 0
LOG('WARNING ActivityTool', 0, LOG('WARNING ActivityTool', 0,
'Could not call method %s on objects %s' % (method_id, expanded_object_list), error=sys.exc_info()) 'Could not call method %s on objects %s' % (method_id, expanded_object_list), error=sys.exc_info())
else: else:
# Obtain all indices of failed messages. Note that this can be a partial failure.
failed_message_dict = {}
for obj in expanded_object_list:
path = obj.getPath()
i = path_dict[path]
failed_message_dict[i] = None
# Only for succeeded messages, an activity process is invoked (if any).
for i in xrange(len(object_list)): for i in xrange(len(object_list)):
object = object_list[i] object = object_list[i]
m = new_message_list[i] m = new_message_list[i]
try: if i in failed_message_dict:
m.activateResult(self, result, object)
m.is_executed = 1
except ConflictError:
raise
except:
m.is_executed = 0 m.is_executed = 0
LOG('WARNING ActivityTool', 0, LOG('WARNING ActivityTool', 0,
'Could not call method %s on object %s' % (m.method_id, m.object_path), error=sys.exc_info()) 'the method %s partially failed on object %s' % (m.method_id, m.object_path,))
else:
try:
m.activateResult(self, result, object)
m.is_executed = 1
except ConflictError:
raise
except:
m.is_executed = 0
LOG('WARNING ActivityTool', 0,
'Could not call method %s on object %s' % (m.method_id, m.object_path), error=sys.exc_info())
def newMessage(self, activity, path, active_process, activity_kw, method_id, *args, **kw): def newMessage(self, activity, path, active_process, activity_kw, method_id, *args, **kw):
# Some Security Cheking should be made here XXX # Some Security Cheking should be made here XXX
......
...@@ -31,6 +31,7 @@ from AccessControl.DTML import RestrictedDTML ...@@ -31,6 +31,7 @@ from AccessControl.DTML import RestrictedDTML
import string, os, sys, types import string, os, sys, types
import time import time
import urllib import urllib
from ZODB.POSException import ConflictError
from zLOG import LOG from zLOG import LOG
...@@ -614,6 +615,7 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -614,6 +615,7 @@ class ZCatalog(Folder, Persistent, Implicit):
hot_reindexing = 1 hot_reindexing = 1
wrapped_object_list = [] wrapped_object_list = []
failed_object_list = []
url_list = [] url_list = []
for obj in object_list: for obj in object_list:
if hot_reindexing: if hot_reindexing:
...@@ -627,8 +629,15 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -627,8 +629,15 @@ class ZCatalog(Folder, Persistent, Implicit):
url = string.join(url(), '/') url = string.join(url(), '/')
url_list.append(url) url_list.append(url)
obj = self.wrapObject(obj, sql_catalog_id=sql_catalog_id) try:
wrapped_object_list.append(obj) obj = self.wrapObject(obj, sql_catalog_id=sql_catalog_id)
except ConflictError:
raise
except:
LOG('WARNING ZSQLCatalog', 0, 'wrapObject failed on the object %r' % (obj,), error=sys.exc_info())
failed_object_list.append(obj)
else:
wrapped_object_list.append(obj)
catalog = self.getSQLCatalog(sql_catalog_id) catalog = self.getSQLCatalog(sql_catalog_id)
if catalog is not None: if catalog is not None:
...@@ -642,6 +651,8 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -642,6 +651,8 @@ class ZCatalog(Folder, Persistent, Implicit):
destination_catalog.deleteRecordedObjectList(url_list) # Prevent this object from being replayed. destination_catalog.deleteRecordedObjectList(url_list) # Prevent this object from being replayed.
destination_catalog.catalogObjectList(wrapped_object_list) destination_catalog.catalogObjectList(wrapped_object_list)
object_list[:] = failed_object_list[:]
def uncatalog_object(self, uid, sql_catalog_id=None): def uncatalog_object(self, uid, sql_catalog_id=None):
""" wrapper around catalog """ """ wrapper around catalog """
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment