diff --git a/product/CMFActivity/skins/activity/SQLDict_hasMessage.zsql b/product/CMFActivity/skins/activity/SQLDict_hasMessage.zsql index 88b4de934e957a839746e850d92ff3ce37d4c371..87f9da9d4a0c5431fe3026d1559a4de8a41ae9d1 100644 --- a/product/CMFActivity/skins/activity/SQLDict_hasMessage.zsql +++ b/product/CMFActivity/skins/activity/SQLDict_hasMessage.zsql @@ -8,13 +8,13 @@ class_name: class_file: </dtml-comment> <params>path -method_id</params> +method_id +only_valid</params> SELECT count(path) as message_count FROM message -<dtml-if "path or method_id"> WHERE -<dtml-if path> path = <dtml-sqlvar path type="string"></dtml-if> +1 = 1 +<dtml-if path> AND path = <dtml-sqlvar path type="string"></dtml-if> <dtml-if method_id>AND method_id = <dtml-sqlvar method_id type="string"></dtml-if> -</dtml-if> +<dtml-if only_valid>AND processing_node > -2</dtml-if> - diff --git a/product/CMFActivity/skins/activity/SQLQueue_hasMessage.zsql b/product/CMFActivity/skins/activity/SQLQueue_hasMessage.zsql index 734a114414c8a86440969734ec15b032c452e48d..8302bd328c198c7c7d989df4cc4c4e273a1992bb 100644 --- a/product/CMFActivity/skins/activity/SQLQueue_hasMessage.zsql +++ b/product/CMFActivity/skins/activity/SQLQueue_hasMessage.zsql @@ -8,12 +8,13 @@ class_name: class_file: </dtml-comment> <params>path -method_id</params> +method_id +only_valid</params> SELECT count(path) as message_count FROM message_queue -<dtml-if "path or method_id"> WHERE -<dtml-if path> path = <dtml-sqlvar path type="string"></dtml-if> +1 = 1 +<dtml-if path>AND path = <dtml-sqlvar path type="string"></dtml-if> <dtml-if method_id>AND method_id = <dtml-sqlvar method_id type="string"></dtml-if> -</dtml-if> - +<dtml-if only_valid>AND processing_node > -2</dtml-if> + diff --git a/product/ERP5/Document/Alarm.py b/product/ERP5/Document/Alarm.py index f0c033df701de8b106e821574dc219516d689fdc..a8c5993668e3944e4e3275c0da606a2bd6787800 100644 --- a/product/ERP5/Document/Alarm.py +++ b/product/ERP5/Document/Alarm.py @@ -264,7 +264,7 @@ class Alarm(XMLObject, PeriodicityMixin): active or not. It is activated when it is doing some calculation with activeSense or solve. """ - return self.hasActivity() + return self.hasActivity(only_valid=1) security.declareProtected(Permissions.ModifyPortalContent, 'activeSense') def activeSense(self): diff --git a/product/ERP5/tests/testAlarm.py b/product/ERP5/tests/testAlarm.py index d8bb74a87be6c38c15552bea3cd11184b77817f9..a0fdba61b1e24a5d32c4c9ff36245af3cefbb805 100644 --- a/product/ERP5/tests/testAlarm.py +++ b/product/ERP5/tests/testAlarm.py @@ -421,7 +421,51 @@ class TestAlarm(ERP5TypeTestCase): get_transaction().commit() self.tic() self.assertEquals(active_process, alarm.getLastActiveProcess()) - + + def test_15_FailedAlarmsDoNotBlockFutureAlarms(self, quiet=0, run=run_all_test): + if not run: return + if not quiet: + message = 'Test Failed Alarms Do Not Block Future Alarms' + ZopeTestCase._print('\n%s ' % message) + LOG('Testing... ',0,message) + sense_method_id = 'Alarm_testSenseMethod' + skin_folder_id = 'custom' + skin_folder = self.getPortal().portal_skins[skin_folder_id] + skin_folder.manage_addProduct['PythonScripts'].manage_addPythonScript(id=sense_method_id) + # Make the sense method fail + skin_folder[sense_method_id].ZPythonScript_edit('*args,**kw', 'raise Exception') + del skin_folder + alarm = self.newAlarm() + now = DateTime() + alarm.setActiveSenseMethodId(sense_method_id) + self.assertEquals(alarm.isActive(), 0) + alarm.activeSense() + get_transaction().commit() + try: + self.tic() + except RuntimeError: + pass + else: + raise Exception, 'Tic did not raise though activity was supposed to fail' + # Check that the alarm is not considered active, although there is a remaining activity. + self.assertEquals(alarm.hasActivity(), 1) + self.assertEquals(alarm.isActive(), 0) + self.assertEquals(alarm.getLastActiveProcess(), None) + # Make the sense method succeed and leave a trace + self.getPortal().portal_skins[skin_folder_id][sense_method_id].ZPythonScript_edit('*args,**kw', 'context.newActiveProcess()') + alarm.activeSense() + get_transaction().commit() + # Note: this call to tic will not fail, because the same method on the same + # object is activated again in SQLDict. When the new message will be + # -successfully- processed, the previous -failed- message will get removed + # in the cleanup. This behaviour is logical if we consider that manually + # executing the failed message to get the error will lead to no error. + # But it can also be considered illogical if failed messages are supposed + # to be preserved for future analysis. + self.tic() + # Chen that the second alarm execution did happen + self.assertNotEquals(alarm.getLastActiveProcess(), None) + if __name__ == '__main__': framework() else: