Commit 35e31f67 authored by Vincent Pelletier's avatar Vincent Pelletier

all: Avoid most direct calls to {recursiveI,i}mmediateReindexObject

These methods must not be called synchronously:
- they can break catalog by not being careful enough about other
  reindexations which may happen in parallel. See the serialization_tag
  mechanism for more.
- indexation gets executed in the security context of the user causing the
  call, which may lead to an indexation result different from what happens
  when indexation happens with an all-accesses user.

Also, simplify a few scripts while doing so.
parent b639160e
""" This script reindex all the objects created before updating local roles """ """ This script reindex all the objects created before updating local roles """
module_list = ['document_module',
'image_module',
'knowledge_pad_module',
'organisation_module',
'person_module',
'review_module',
'test_page_module',
'web_page_module',
'web_site_module']
context.portal_types.recursiveImmediateReindexObject()
portal = context.getPortalObject() portal = context.getPortalObject()
for module_id in module_list: portal.portal_types.Folder_reindexAll()
module = getattr(portal, module_id) stack = [
module.recursiveImmediateReindexObject() portal.document_module,
stack = [module] portal.image_module,
for obj in stack: portal.knowledge_pad_module,
for child in obj.objectValues(): portal.organisation_module,
stack.append(child) portal.person_module,
portal.review_module,
portal.test_page_module,
portal.web_page_module,
portal.web_site_module,
]
for obj in stack:
stack.extend(obj.objectValues())
obj.updateLocalRolesOnSecurityGroups() obj.updateLocalRolesOnSecurityGroups()
obj.reindexObjectSecurity()
from Products.ERP5Type.ImmediateReindexContextManager import ImmediateReindexContextManager
changed_object = state_change['object'] changed_object = state_change['object']
portal = changed_object.getPortalObject() portal = changed_object.getPortalObject()
...@@ -28,7 +29,9 @@ else: ...@@ -28,7 +29,9 @@ else:
# create the person wich represent the company # create the person wich represent the company
person_module = portal.getDefaultModule(portal_type='Person') person_module = portal.getDefaultModule(portal_type='Person')
accountant = person_module.newContent(portal_type='Person', with ImmediateReindexContextManager() as immediate_reindex_context_manager:
accountant = person_module.newContent(portal_type='Person',
immediate_reindex=immediate_reindex_context_manager,
title=changed_object.getAccountantName(), title=changed_object.getAccountantName(),
default_telephone_text=changed_object.getAccountantTelNumber(), default_telephone_text=changed_object.getAccountantTelNumber(),
default_fax_text=changed_object.getAccountantFax(), default_fax_text=changed_object.getAccountantFax(),
...@@ -38,19 +41,17 @@ accountant = person_module.newContent(portal_type='Person', ...@@ -38,19 +41,17 @@ accountant = person_module.newContent(portal_type='Person',
career_subordination_value=organisation) career_subordination_value=organisation)
# create an assignment to be able to login : # create an assignment to be able to login :
from DateTime import DateTime assignment = accountant.newContent(portal_type='Assignment')
assignment = accountant.newContent(portal_type='Assignment') assignment.setStartDate(DateTime())
assignment.setStartDate(DateTime()) assignment.setStopDate(DateTime()+365)
assignment.setStopDate(DateTime()+365) assignment.setCareerFunction(changed_object.getAccountantFunction())
assignment.setCareerFunction(changed_object.getAccountantFunction()) assignment.open()
assignment.open()
# set the login and password required a manager role, so a script with a
# set the login and password required a manager role, so a script with a # proxy role is used
# proxy role is used login = context.generateNewLogin(text=changed_object.getAccountantName())
login = context.generateNewLogin(text=changed_object.getAccountantName()) password = changed_object.Person_generatePassword()
password = changed_object.Person_generatePassword() context.EGov_setLoginAndPasswordAsManager(accountant, login, password)
context.EGov_setLoginAndPasswordAsManager(accountant, login, password)
accountant.immediateReindexObject()
accountant.Person_sendCrendentialsByEMail() accountant.Person_sendCrendentialsByEMail()
pad = context.knowledge_pad_module.newContent(portal_type='Knowledge Pad', from Products.ERP5Type.ImmediateReindexContextManager import ImmediateReindexContextManager
with ImmediateReindexContextManager() as immediate_reindex_context_manager:
pad = context.knowledge_pad_module.newContent(portal_type='Knowledge Pad',
immediate_reindex=immediate_reindex_context_manager,
title = pad_title) title = pad_title)
# for web mode # for web mode
if mode in ('web_front', 'web_section',): if mode in ('web_front', 'web_section',):
# in Web Mode we can have a temporary Web Site objects created based on current language # in Web Mode we can have a temporary Web Site objects created based on current language
real_context = context.Base_getRealContext() real_context = context.Base_getRealContext()
pad.setPublicationSectionValue(real_context) pad.setPublicationSectionValue(real_context)
# set it as active # set it as active
context.ERP5Site_toggleActiveKnowledgePad(pad, mode=mode, redirect=False) context.ERP5Site_toggleActiveKnowledgePad(pad, mode=mode, redirect=False)
# See ERP5Site_createDefaultKnowledgePadListForUser
pad.immediateReindexObject()
if redirect_url: if redirect_url:
return context.REQUEST.RESPONSE.redirect(redirect_url) return context.REQUEST.RESPONSE.redirect(redirect_url)
......
from Products.ERP5Type.ImmediateReindexContextManager import ImmediateReindexContextManager
knowledge_pad = None knowledge_pad = None
portal = context.getPortalObject() portal = context.getPortalObject()
system_pref = context.portal_preferences.getActiveSystemPreference() system_pref = context.portal_preferences.getActiveSystemPreference()
...@@ -13,9 +14,10 @@ else: ...@@ -13,9 +14,10 @@ else:
# find from preferences for the same context(site, section, page) # find from preferences for the same context(site, section, page)
filter_pad = lambda x: context in x.getPublicationSectionValueList() filter_pad = lambda x: context in x.getPublicationSectionValueList()
# try to find template KnowledgePad from System Preference (and user Preference with ImmediateReindexContextManager() as immediate_reindex_context_manager:
# for backward compatibility only). # try to find template KnowledgePad from System Preference (and user Preference
for pref in (system_pref, user_pref): # for backward compatibility only).
for pref in (system_pref, user_pref):
if pref is not None: if pref is not None:
# use template from preferences # use template from preferences
for pref_pad in pref.objectValues(portal_type='Knowledge Pad'): for pref_pad in pref.objectValues(portal_type='Knowledge Pad'):
...@@ -23,9 +25,10 @@ for pref in (system_pref, user_pref): ...@@ -23,9 +25,10 @@ for pref in (system_pref, user_pref):
break break
else: else:
continue continue
cp = pref.manage_copyObjects(ids=[pref_pad.getId()])
new_id = context.knowledge_pad_module.manage_pasteObjects( new_id = context.knowledge_pad_module.manage_pasteObjects(
cb_copy_data=cp)[0]['new_id'] cb_copy_data=pref.manage_copyObjects(ids=[pref_pad.getId()]),
immediate_reindex=immediate_reindex_context_manager,
)[0]['new_id']
knowledge_pad = context.knowledge_pad_module[new_id] knowledge_pad = context.knowledge_pad_module[new_id]
knowledge_pad.makeTemplateInstance() knowledge_pad.makeTemplateInstance()
# set each contaned box's state manually to visible # set each contaned box's state manually to visible
...@@ -34,12 +37,14 @@ for pref in (system_pref, user_pref): ...@@ -34,12 +37,14 @@ for pref in (system_pref, user_pref):
for box in knowledge_pad.contentValues(portal_type='Knowledge Box'): for box in knowledge_pad.contentValues(portal_type='Knowledge Box'):
box.visible() box.visible()
break break
else: else:
# created empty one because no template found # created empty one because no template found
knowledge_pad = context.knowledge_pad_module.newContent( knowledge_pad = context.knowledge_pad_module.newContent(
immediate_reindex=immediate_reindex_context_manager,
portal_type = 'Knowledge Pad', portal_type = 'Knowledge Pad',
title = context.Base_translateString('Tab 1')) title = context.Base_translateString('Tab 1'),
if is_web_mode: )
if is_web_mode:
# in Web Mode we can have a temporary Web Site objects created based on current language # in Web Mode we can have a temporary Web Site objects created based on current language
real_context = context.Base_getRealContext() real_context = context.Base_getRealContext()
if real_context.getPortalType() == 'Web Site' and not default_pad_group: if real_context.getPortalType() == 'Web Site' and not default_pad_group:
...@@ -51,23 +56,16 @@ if is_web_mode: ...@@ -51,23 +56,16 @@ if is_web_mode:
# layout definition # layout definition
knowledge_pad.setGroup(default_pad_group) knowledge_pad.setGroup(default_pad_group)
knowledge_pad.visible() knowledge_pad.visible()
# set owner # set owner
if owner is not None: if owner is not None:
current_user = context.portal_membership.getAuthenticatedMember() current_user = context.portal_membership.getAuthenticatedMember()
knowledge_pad.manage_setLocalRoles(userid=owner, roles=['Owner']) knowledge_pad.manage_setLocalRoles(userid=owner, roles=['Owner'])
knowledge_pad.manage_delLocalRoles([current_user.getIdOrUserName()]) knowledge_pad.manage_delLocalRoles([current_user.getIdOrUserName()])
knowledge_pad.reindexObject() knowledge_pad.reindexObject()
# set default gadgets # set default gadgets
context.ERP5Site_createDefaultKnowledgeBox(knowledge_pad) context.ERP5Site_createDefaultKnowledgeBox(knowledge_pad)
# Calling immediateReindexObject explicitly is a coding crime.
# But it's safe for newly created objects and this script should
# be called rarely enough to not cause any performance issue.
# Any other solution would be more complicated.
# See also ERP5Site_addNewKnowledgePad
knowledge_pad.immediateReindexObject()
if REQUEST is None: if REQUEST is None:
return knowledge_pad return knowledge_pad
from Products.ERP5Type.ImmediateReindexContextManager import ImmediateReindexContextManager
follow_up_value = context.getPortalObject().restrictedTraverse(follow_up) follow_up_value = context.getPortalObject().restrictedTraverse(follow_up)
assert follow_up_value.getPortalType() == "Support Request" assert follow_up_value.getPortalType() == "Support Request"
follow_up_value.edit() # update modification date follow_up_value.edit() # update modification date
post = context.PostModule_createHTMLPostFromText( with ImmediateReindexContextManager() as immediate_reindex_context_manager:
post = context.PostModule_createHTMLPostFromText(
follow_up=follow_up, follow_up=follow_up,
data=data, data=data,
) immediate_reindex_context_manager=immediate_reindex_context_manager,
)
if file not in ("undefined", None): # XXX "undefined" ? should also be fixed in javascript side if file not in ("undefined", None): # XXX "undefined" ? should also be fixed in javascript side
document_kw = {'batch_mode': True, document_kw = {'batch_mode': True,
'redirect_to_document': False, 'redirect_to_document': False,
'file': file} 'file': file}
...@@ -20,7 +23,4 @@ if file not in ("undefined", None): # XXX "undefined" ? should also be fixed in ...@@ -20,7 +23,4 @@ if file not in ("undefined", None): # XXX "undefined" ? should also be fixed in
# XXX depending on security model this should be changed accordingly # XXX depending on security model this should be changed accordingly
document.publish() document.publish()
post.publish() post.publish()
# XXX in support request web app interface, discussable page reloads right after
# adding a post, searching for new post hoping it is already indexed.
post.immediateReindexObject()
from Products.ERP5Type.ImmediateReindexContextManager import ImmediateReindexContextManager
portal = context.getPortalObject() portal = context.getPortalObject()
logged_in_user_value = portal.portal_membership.getAuthenticatedMember().getUserValue() logged_in_user_value = portal.portal_membership.getAuthenticatedMember().getUserValue()
...@@ -7,7 +8,13 @@ now = DateTime() ...@@ -7,7 +8,13 @@ now = DateTime()
project_list = portal.portal_catalog(portal_type="Project", id=project) # with id keyword, this function will return a sequence data type which contains one element. project_list = portal.portal_catalog(portal_type="Project", id=project) # with id keyword, this function will return a sequence data type which contains one element.
project_object = project_list[0].getObject() project_object = project_list[0].getObject()
# support_request.Base_getRelatedPostList with ImmediateReindexContextManager() as immediate_reindex_context_manager:
support_request = portal.support_request_module.newContent(
immediate_reindex=immediate_reindex_context_manager,
portal_type='Support Request',
title=title,
resource="service_module/" + resource,
)
# - Reference = automatically generated - already implemented # - Reference = automatically generated - already implemented
# - Requester = current user person # - Requester = current user person
...@@ -17,7 +24,7 @@ project_object = project_list[0].getObject() ...@@ -17,7 +24,7 @@ project_object = project_list[0].getObject()
# - Location = Project related Location # - Location = Project related Location
# - Supervisor = Project related Supervisor # - Supervisor = Project related Supervisor
support_request = portal.support_request_module.newContent( support_request = portal.support_request_module.newContent(
portal_type='Support Request', portal_type='Support Request',
title=title, title=title,
resource="service_module/" + resource, resource="service_module/" + resource,
...@@ -27,11 +34,10 @@ support_request = portal.support_request_module.newContent( ...@@ -27,11 +34,10 @@ support_request = portal.support_request_module.newContent(
source_project_value = project_object, source_project_value = project_object,
destination_value = project_object.getDestinationValue(), destination_value = project_object.getDestinationValue(),
start_date=now, start_date=now,
) )
support_request.submit() support_request.submit()
support_request.immediateReindexObject()
if description is not None or file is not None: if description is not None or file is not None:
portal.post_module.PostModule_createHTMLPostForSupportRequest( portal.post_module.PostModule_createHTMLPostForSupportRequest(
......
...@@ -13,6 +13,7 @@ if predecessor not in (None, ""): ...@@ -13,6 +13,7 @@ if predecessor not in (None, ""):
predecessor_value, = portal.portal_catalog(relative_url=predecessor, limit=2) predecessor_value, = portal.portal_catalog(relative_url=predecessor, limit=2)
post_edit_kw["predecessor_value"] = predecessor_value.getObject() post_edit_kw["predecessor_value"] = predecessor_value.getObject()
post = post_module.newContent( post = post_module.newContent(
immediate_reindex=immediate_reindex_context_manager,
portal_type='HTML Post', portal_type='HTML Post',
**post_edit_kw **post_edit_kw
) )
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>follow_up, data, predecessor=None</string> </value> <value> <string>follow_up, data, predecessor=None, immediate_reindex_context_manager=None</string> </value>
</item> </item>
<item> <item>
<key> <string>_proxy_roles</string> </key> <key> <string>_proxy_roles</string> </key>
......
...@@ -2,4 +2,5 @@ return context.PostModule_createHTMLPost( ...@@ -2,4 +2,5 @@ return context.PostModule_createHTMLPost(
follow_up=follow_up, follow_up=follow_up,
predecessor=predecessor, predecessor=predecessor,
data="<p>" + data.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace(" ", " &nbsp;").replace("\n", "<br/>") + "</p>", data="<p>" + data.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace(" ", " &nbsp;").replace("\n", "<br/>") + "</p>",
immediate_reindex_context_manager=immediate_reindex_context_manager,
) )
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>follow_up, data, predecessor=None</string> </value> <value> <string>follow_up, data, predecessor=None, immediate_reindex_context_manager=None</string> </value>
</item> </item>
<item> <item>
<key> <string>_proxy_roles</string> </key> <key> <string>_proxy_roles</string> </key>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# key of dict : id of resource # key of dict : id of resource
# item of dict : tuples (resource_value, variation_category_list, quantity) # item of dict : tuples (resource_value, variation_category_list, quantity)
from ZTUtils import make_query from ZTUtils import make_query
from Products.ERP5Type.ImmediateReindexContextManager import ImmediateReindexContextManager
delivery = context delivery = context
next_container_number = next_container_int_index next_container_number = next_container_int_index
...@@ -28,13 +29,17 @@ for listitem in listbox : ...@@ -28,13 +29,17 @@ for listitem in listbox :
(movement.getVariationCategoryList(), (movement.getVariationCategoryList(),
container_quantity)] container_quantity)]
# we build 'container_count' containers with ImmediateReindexContextManager() as immediate_reindex_context_manager:
for container_number in range(container_count) : # we build 'container_count' containers
for container_number in range(container_count):
new_container_id = 'c'+str(next_container_number) new_container_id = 'c'+str(next_container_number)
# we use container_type to know which are the resource (and variation) # we use container_type to know which are the resource (and variation)
# of the container # of the container
container = delivery.newContent( container = delivery.newContent(
# Container must be immediately reindexed,
# in order to see good packed quantity in fast input form
immediate_reindex=immediate_reindex_context_manager,
portal_type="Container", portal_type="Container",
title=new_container_id, title=new_container_id,
int_index=next_container_number, int_index=next_container_number,
...@@ -56,10 +61,10 @@ for container_number in range(container_count) : ...@@ -56,10 +61,10 @@ for container_number in range(container_count) :
for variation_category_list, quantity in desired_lines[resource_url]: for variation_category_list, quantity in desired_lines[resource_url]:
for variation_item in variation_category_list: for variation_item in variation_category_list:
if not variation_item in line_variation_category_list : if not variation_item in line_variation_category_list:
line_variation_category_list.append(variation_item) line_variation_category_list.append(variation_item)
variation_base_category_items = variation_item.split('/') variation_base_category_items = variation_item.split('/')
if len(variation_base_category_items) > 0 : if len(variation_base_category_items) > 0:
line_variation_base_category_dict[variation_base_category_items[0]] = 1 line_variation_base_category_dict[variation_base_category_items[0]] = 1
line_variation_base_category_list = line_variation_base_category_dict.keys() line_variation_base_category_list = line_variation_base_category_dict.keys()
...@@ -68,6 +73,7 @@ for container_number in range(container_count) : ...@@ -68,6 +73,7 @@ for container_number in range(container_count) :
resource_url = resource_url resource_url = resource_url
new_container_line_id = str(container.generateNewId()) new_container_line_id = str(container.generateNewId())
container_line = container.newContent( container_line = container.newContent(
immediate_reindex=immediate_reindex_context_manager,
portal_type="Container Line", portal_type="Container Line",
title=new_container_line_id, title=new_container_line_id,
resource=resource_url, resource=resource_url,
...@@ -83,6 +89,7 @@ for container_number in range(container_count) : ...@@ -83,6 +89,7 @@ for container_number in range(container_count) :
base_id = 'movement' base_id = 'movement'
if not container_line.hasCell(base_id=base_id, *cell_key): if not container_line.hasCell(base_id=base_id, *cell_key):
cell = container_line.newCell( cell = container_line.newCell(
immediate_reindex=immediate_reindex_context_manager,
base_id=base_id, base_id=base_id,
portal_type="Container Cell", portal_type="Container Cell",
*cell_key *cell_key
...@@ -94,10 +101,6 @@ for container_number in range(container_count) : ...@@ -94,10 +101,6 @@ for container_number in range(container_count) :
line_variation_base_category_list) line_variation_base_category_list)
cell.edit(quantity=quantity) cell.edit(quantity=quantity)
# Container must be immediately reindexed,
# in order to see good packed quantity in fast input form
container.recursiveImmediateReindexObject()
url_params = make_query(selection_name=selection_name, url_params = make_query(selection_name=selection_name,
dialog_category=dialog_category, dialog_category=dialog_category,
form_id=form_id, form_id=form_id,
......
...@@ -3262,14 +3262,8 @@ class TestAccessControl(ERP5TypeTestCase): ...@@ -3262,14 +3262,8 @@ class TestAccessControl(ERP5TypeTestCase):
method.setFiltered(1) method.setFiltered(1)
method.setExpression(self.expression) method.setExpression(self.expression)
createZODBPythonScript(self.getSkinsTool().custom,
'Base_immediateReindexObject',
'',
'context.immediateReindexObject()'
).manage_proxy(('Manager',))
def test(self): def test(self):
self.portal.person_module.newContent().Base_immediateReindexObject() self.portal.person_module.newContent(immediate_reindex=True)
def test_suite(): def test_suite():
......
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