Commit 9a1cb966 authored by Jérome Perrin's avatar Jérome Perrin

Fix "incremental check" mode of consistency check alarm

The way consistency check select documents to check at each run when running incremental mode, consistency seems to have issues which leads to documents not checked sometimes.

I noticed two reasons:
* When Zope runs with a timezone that is not `UTC`, the date comparison to find new documents compares a date in zope local timezone with a timestamp in mysql timezone. First fix is to pass a date to catalog, so that catalog convert it to the catalog timezone (it's a mistake to pass a date as string when using catalog programmatically). Second fix seem that we seem to need to configure mariadb to use `UTC` by default.
* `alarm.getLastActiveProcess` does not return the latest active process when alarm is executing `activeSense` so we need to pass `include_active=True` in this case.

/reviewed-on nexedi/erp5!537
parents 6c2435cf e88cf4ad
kw = {} kw = {}
if context.getProperty('incremental_check'): if context.getProperty('incremental_check'):
last_active_process = context.getLastActiveProcess() last_active_process = context.getLastActiveProcess(include_active=True)
if last_active_process is not None: if last_active_process is not None:
kw['indexation_timestamp'] = '>= %s' % last_active_process.getStartDate().ISO() kw['indexation_timestamp'] = {
'query': last_active_process.getStartDate(),
'range': '>='
}
active_process = context.newActiveProcess().getRelativeUrl() active_process = context.newActiveProcess().getRelativeUrl()
query_string = context.getProperty('catalog_query_string', '') query_string = context.getProperty('catalog_query_string', '')
...@@ -13,8 +16,16 @@ portal = context.getPortalObject() ...@@ -13,8 +16,16 @@ portal = context.getPortalObject()
if query_string is not None: if query_string is not None:
kw.update(SearchableText=query_string) kw.update(SearchableText=query_string)
kw.update(parent_uid=[portal.restrictedTraverse(module).getUid() for module in context.getProperty('module_list') or []]) parent_uid =[portal.restrictedTraverse(module).getUid()
for module in context.getProperty('module_list') or []]
if parent_uid:
kw.update(parent_uid=parent_uid)
portal.portal_catalog.searchAndActivate(method_id='Base_checkAlarmConsistency', method_kw={'fixit': fixit, 'active_process': active_process}, activate_kw={'tag':tag, 'priority': 8}, **kw)
portal.portal_catalog.searchAndActivate(
method_id='Base_checkAlarmConsistency',
method_kw={'fixit': fixit, 'active_process': active_process},
activate_kw={'tag':tag, 'priority': 8},
**kw)
context.activate(after_tag=tag).getId() context.activate(after_tag=tag).getId()
...@@ -9,8 +9,11 @@ if context.providesIConstraint(): ...@@ -9,8 +9,11 @@ if context.providesIConstraint():
# of this name implement consistency checking on object # of this name implement consistency checking on object
return constraint_message_list return constraint_message_list
# this constraint is created as a temp object under portal_trash, because
# portal_trash has no restriction on allowed content types.
missing_category_document = portal.portal_trash.newContent( missing_category_document = portal.portal_trash.newContent(
portal_type='Missing Category Document Constraint', portal_type='Missing Category Document Constraint',
id='missing_category_document_constraint',
temp_object=True) temp_object=True)
property_type_validity = PropertyTypeValidity(id='type_check', description='Type Validity Check') property_type_validity = PropertyTypeValidity(id='type_check', description='Type Validity Check')
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
############################################################################## ##############################################################################
import unittest import unittest
import time
from Products.ERP5.tests.testInventoryAPI import InventoryAPITestCase from Products.ERP5.tests.testInventoryAPI import InventoryAPITestCase
class TestERP5Administration(InventoryAPITestCase): class TestERP5Administration(InventoryAPITestCase):
...@@ -83,11 +84,10 @@ class TestERP5Administration(InventoryAPITestCase): ...@@ -83,11 +84,10 @@ class TestERP5Administration(InventoryAPITestCase):
def test_check_consistency_alarm(self): def test_check_consistency_alarm(self):
alarm = self.portal.portal_alarms.check_consistency alarm = self.portal.portal_alarms.check_consistency
# Here we disable user_id so that Person_createUserPreference will not be called inconsistent_document = self.portal.organisation_module.newContent(
# automatically. portal_type='Organisation')
person = self.portal.person_module.newContent(portal_type='Person', user_id=None)
# this document will be non consistent, for PropertyTypeValidity # this document will be non consistent, for PropertyTypeValidity
person.title = 3 inconsistent_document.title = 3
# tic right now to make sure the person is indexed, indeed the alarm # tic right now to make sure the person is indexed, indeed the alarm
# could use catalog to retrieve objects to check # could use catalog to retrieve objects to check
self.tic() self.tic()
...@@ -112,7 +112,39 @@ class TestERP5Administration(InventoryAPITestCase): ...@@ -112,7 +112,39 @@ class TestERP5Administration(InventoryAPITestCase):
# case of PropertyTypeValidity # case of PropertyTypeValidity
alarm.solve() alarm.solve()
self.tic() self.tic()
self.assertEqual('3', person.title) self.assertEqual('3', inconsistent_document.title)
def test_check_consistency_incremental(self):
alarm = self.portal.portal_alarms.check_consistency.Base_createCloneDocument(
batch_mode=True)
alarm.edit(incremental_check=True)
alarm.activeSense()
self.tic()
# create an inconsistent document
inconsistent_document = self.portal.organisation_module.newContent(
portal_type='Organisation')
inconsistent_document.title = 0
self.tic()
# alarm report this document as not consistent
time.sleep(2) # catalog date columns have a one second precision
alarm.activeSense()
self.tic()
self.assertTrue(alarm.sense())
result, = alarm.getLastActiveProcess().getResultList()
constraint_message, = result.getProperty('constraint_message_list')
self.assertEqual(inconsistent_document.getRelativeUrl(), constraint_message.object_relative_url)
# next time the alarm run, document is not reported anymore
alarm.activeSense()
self.tic()
self.assertFalse(alarm.sense())
self.assertEqual([], alarm.getLastActiveProcess().getResultList())
# cleanup
self.portal.organisation_module.manage_delObjects(
ids=[inconsistent_document.getId()])
self.tic()
def test_missing_category_document_constraint(self): def test_missing_category_document_constraint(self):
person = self.portal.person_module.newContent(portal_type='Person') person = self.portal.person_module.newContent(portal_type='Person')
......
...@@ -382,7 +382,7 @@ Alarm Tool Node: %s ...@@ -382,7 +382,7 @@ Alarm Tool Node: %s
limit = 1 limit = 1
else: else:
limit = self.isActive() and 2 or 1 limit = self.isActive() and 2 or 1
active_process_list = self.getPortalObject().portal_catalog( active_process_list = self.getPortalObject().portal_catalog.unrestrictedSearchResults(
portal_type='Active Process', limit=limit, portal_type='Active Process', limit=limit,
sort_on=(('creation_date', 'DESC'), sort_on=(('creation_date', 'DESC'),
('id', 'DESC', 'UNSIGNED'),), ('id', 'DESC', 'UNSIGNED'),),
......
...@@ -314,6 +314,7 @@ class DB(TM): ...@@ -314,6 +314,7 @@ class DB(TM):
error=True, error=True,
) )
self.db = MySQLdb.connect(**self._kw_args) self.db = MySQLdb.connect(**self._kw_args)
self._query("SET time_zone='+00:00'")
def tables(self, rdb=0, def tables(self, rdb=0,
_care=('TABLE', 'VIEW')): _care=('TABLE', 'VIEW')):
......
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