def test_expiration_policy_for_executions(self): # Delete execution uses a secured filtering and we need # to verify that admin able to do that for other projects. cfg.CONF.set_default('auth_enable', True, group='pecan') # Since we are removing other projects execution, # we want to load the executions with other project_id. _switch_context('non_admin_project', False) _load_executions() now = datetime.datetime.now() # This execution has a parent wf and testing that we are # querying only for parent wfs. exec_child = db_api.get_execution('654') self.assertEqual('789', exec_child.task_execution_id) # Call for all expired wfs execs. execs = db_api.get_expired_executions(now) # Should be only 3, the RUNNING execution shouldn't return, # so the child wf (that has parent task id). self.assertEqual(3, len(execs)) # Switch context to Admin since expiration policy running as Admin. _switch_context(None, True) # TODO(m4dcoder): The expiration policy is changed here to expire # executions older than 30 minutes. It was originally 10 minutes. # The unit test below expects 1 execution to remain after the policy # is applied. However, the unit test fail frequently because the # process that deletes the expired executions seem to run late and # all executions are deleted. The unit tests seems to run better if # the config is changed to 30 minutes. Troubleshoot the expiration # policy to identify cause of the delay. _set_expiration_policy_config(1, 30) expiration_policy.run_execution_expiration_policy(self, ctx) # Only non_expired available (update_at < older_than). execs = db_api.get_expired_executions(now) self.assertEqual(1, len(execs)) self.assertEqual('987', execs[0].id) _set_expiration_policy_config(1, 5) expiration_policy.run_execution_expiration_policy(self, ctx) execs = db_api.get_expired_executions(now) self.assertEqual(0, len(execs))
def run_execution_expiration_policy(self, ctx): LOG.debug("Starting expiration policy task.") older_than = CONF.execution_expiration_policy.older_than exp_time = (datetime.datetime.now() - datetime.timedelta(minutes=older_than)) with db_api.transaction(): # TODO(gpaz): In the future should use generic method with # filters params and not specific method that filter by time. for execution in db_api.get_expired_executions(exp_time): try: # Setup project_id for _secure_query delete execution. ctx = auth_ctx.MistralContext( user_id=None, project_id=execution.project_id, auth_token=None, is_admin=True ) auth_ctx.set_ctx(ctx) LOG.debug( 'DELETE execution id : %s from date : %s ' 'according to expiration policy', execution.id, execution.updated_at ) db_api.delete_workflow_execution(execution.id) except Exception as e: msg = ("Failed to delete [execution_id=%s]\n %s" % (execution.id, traceback.format_exc(e))) LOG.warning(msg) finally: auth_ctx.set_ctx(None)
def test_expiration_policy_for_executions_with_different_project_id(self): # Delete execution uses a secured filtering and we need # to verify that admin able to do that for other projects. cfg.CONF.set_default('auth_enable', True, group='pecan') # Since we are removing other projects execution, # we want to load the executions with other project_id. _switch_context(False, False) _create_workflow_executions() now = datetime.datetime.utcnow() # This execution has a parent wf and testing that we are # querying only for parent wfs. exec_child = db_api.get_workflow_execution('expired_but_not_a_parent') self.assertEqual('running_not_expired', exec_child.task_execution_id) # Call for all expired wfs execs. execs = db_api.get_expired_executions(now) # Should be only 5, the RUNNING execution shouldn't return, # so the child wf (that has parent task id). self.assertEqual(5, len(execs)) # Switch context to Admin since expiration policy running as Admin. _switch_context(True, True) _set_expiration_policy_config(evaluation_interval=1, older_than=30) expiration_policy.run_execution_expiration_policy(self, ctx) # Only non_expired available (update_at < older_than). execs = db_api.get_expired_executions(now) self.assertEqual(2, len(execs)) self.assertListEqual(['cancelled_not_expired', 'success_not_expired'], sorted([ex.id for ex in execs])) _set_expiration_policy_config(evaluation_interval=1, older_than=5) expiration_policy.run_execution_expiration_policy(self, ctx) execs = db_api.get_expired_executions(now) self.assertEqual(0, len(execs))
def test_expiration_policy_for_executions(self): # Delete execution uses a secured filtering and we need # to verify that admin able to do that for other projects. cfg.CONF.set_default('auth_enable', True, group='pecan') # Since we are removing other projects execution, # we want to load the executions with other project_id. _switch_context('non_admin_project', False) _load_executions() now = datetime.datetime.now() # This execution has a parent wf and testing that we are # querying only for parent wfs. exec_child = db_api.get_execution('654') self.assertEqual('789', exec_child.task_execution_id) # Call for all expired wfs execs. execs = db_api.get_expired_executions(now) # Should be only 3, the RUNNING execution shouldn't return, # so the child wf (that has parent task id). self.assertEqual(3, len(execs)) # Switch context to Admin since expiration policy running as Admin. _switch_context(None, True) _set_expiration_policy_config(1, 30) expiration_policy.run_execution_expiration_policy(self, ctx) # Only non_expired available (update_at < older_than). execs = db_api.get_expired_executions(now) self.assertEqual(1, len(execs)) self.assertEqual('987', execs[0].id) _set_expiration_policy_config(1, 5) expiration_policy.run_execution_expiration_policy(self, ctx) execs = db_api.get_expired_executions(now) self.assertEqual(0, len(execs))
def test_deletion_of_expired_executions_with_batch_size_scenario1(self): """scenario1 This test will use batch_size of 3, 5 expired executions and different values of "older_than" which is 30 and 5 minutes respectively. Expected_result: All expired executions are successfully deleted. """ _create_workflow_executions() now = datetime.datetime.utcnow() _set_expiration_policy_config(evaluation_interval=1, older_than=30, batch_size=3) expiration_policy.run_execution_expiration_policy(self, ctx) execs = db_api.get_expired_executions(now) self.assertEqual(2, len(execs)) _set_expiration_policy_config(evaluation_interval=1, older_than=5) expiration_policy.run_execution_expiration_policy(self, ctx) execs = db_api.get_expired_executions(now) self.assertEqual(0, len(execs))
def _delete_executions(batch_size, expiration_time, max_finished_executions): _delete_until_depleted( lambda: db_api.get_expired_executions( expiration_time, batch_size ) ) _delete_until_depleted( lambda: db_api.get_superfluous_executions( max_finished_executions, batch_size ) )
def test_deletion_of_expired_executions_with_batch_size_scenario2(self): """scenario2 This test will use batch_size of 2, 5 expired executions with value of "older_than" that is 5 minutes. Expected_result: All expired executions are successfully deleted. """ _create_workflow_executions() now = datetime.datetime.utcnow() _set_expiration_policy_config(evaluation_interval=1, older_than=5, batch_size=2) expiration_policy.run_execution_expiration_policy(self, ctx) execs = db_api.get_expired_executions(now) self.assertEqual(0, len(execs))