A hard or soft reset should also cause a 'cancel_notify' which will kick off any CANCEL events. If this happens during

a hard or soft reset, and an error is thrown trying to fulfil a cancel event, the reset should still fire.
Sending emails still had a number of issues correctly parsing it's arguments.  This is corrected.
This commit is contained in:
Dan 2020-12-29 18:05:13 -05:00
parent 578f9e4b81
commit e5a38874f6
3 changed files with 40 additions and 55 deletions

View File

@ -102,7 +102,16 @@ def get_workflow(workflow_id, soft_reset=False, hard_reset=False, do_engine_step
Read Only will return the workflow in a read only state, without running any
engine tasks or logging any events. """
workflow_model: WorkflowModel = session.query(WorkflowModel).filter_by(id=workflow_id).first()
processor = WorkflowProcessor(workflow_model, soft_reset=soft_reset, hard_reset=hard_reset)
processor = WorkflowProcessor(workflow_model)
if soft_reset or hard_reset:
try:
processor.cancel_notify()
except Exception as e:
raise e
finally:
# In the event of a reset, ALWAYS allow the reset, even if the cancel_notify fails for some reason.
processor = WorkflowProcessor(workflow_model, soft_reset=soft_reset, hard_reset=hard_reset)
if do_engine_steps:
processor.do_engine_steps()
processor.save()
@ -148,7 +157,7 @@ def set_current_task(workflow_id, task_id):
"currently set to COMPLETE or READY.")
# If we have an interrupt task, run it.
processor.bpmn_workflow.cancel_notify()
processor.cancel_notify()
# Only reset the token if the task doesn't already have it.
if spiff_task.state == spiff_task.COMPLETED:

View File

@ -16,12 +16,12 @@ class Email(Script):
def get_description(self):
return """
Creates an email, using the provided arguments (a list of UIDs)"
Each argument will be used to look up personal information needed for
the email creation.
Creates an email, using the provided arguments. The first argument is the subject of the email,
all subsequent arguments should be email addresses in quotes, or variables containing an email address or a list
of email addresses."
The "documentation" should contain markdown that will become the body of the email message.
Example:
Email Subject ApprvlApprvr1 PIComputingID
email ("My Subject", "dhf8r@virginia.edu", pi.email)
"""
def do_task_validate_only(self, task, *args, **kwargs):
@ -29,15 +29,13 @@ Email Subject ApprvlApprvr1 PIComputingID
self.get_email_recipients(task, args)
self.get_content(task)
def do_task(self, task, *args, **kwargs):
args = [arg for arg in args if type(arg) == str or type(arg) == list]
def do_task(self, task, study_id, workflow_id, *args, **kwargs):
if len(args) < 1:
raise ApiError(code="missing_argument",
message="Email script requires a subject and at least one email address as arguments")
subject = args[0]
recipients = None
try:
recipients = self.get_email_recipients(task, args)
except ApiError:
raise
recipients = self.get_email_recipients(task, args)
content, content_html = self.get_content(task)
if recipients:
send_mail(
@ -59,58 +57,30 @@ Email Subject ApprvlApprvr1 PIComputingID
def get_email_recipients(self, task, args):
emails = []
if len(args[1]) < 1:
if len(args) < 2:
raise ApiError(code="missing_argument",
message="Email script requires at least one email address as an argument. "
"Multiple email addresses are accepted.")
if isinstance(args[1], str):
if self.check_valid_email(args[1]):
emails.append(args[1])
# Every argument following the subject should be an email, or a list of emails.
for arg in args[1:]:
if isinstance(arg, str):
emails_to_check = [arg]
elif isinstance(arg, list):
emails_to_check = arg
else:
raise ApiError(code="invalid_argument",
message="The email address you provided could not be parsed. "
"The value you provided is '%s" % args[1])
message=f"Email script requires a valid email address, but received '{arg}'")
if isinstance(args[1], list):
for address in args[1]:
if self.check_valid_email(address):
emails.append(address)
for e in emails_to_check:
if self.check_valid_email(e):
emails.append(e)
else:
raise ApiError(code="invalid_argument",
message="The email address you provided could not be parsed. "
"The value you provided is '%s" % address)
"The value you provided is '%s" % e)
if len(emails) > 0:
return emails
else:
raise ApiError(code="invalid_argument",
message="Email script requires a valid email address.")
# def get_users_info(self, task, args):
# if len(args) < 1:
# raise ApiError(code="missing_argument",
# message="Email script requires at least one argument. The "
# "name of the variable in the task data that contains user"
# "id to process. Multiple arguments are accepted.")
# emails = []
# for arg in args:
# try:
# uid = task.workflow.script_engine.evaluate_expression(task, arg)
# except Exception as e:
# app.logger.error(f'Workflow engines could not parse {arg}', exc_info=True)
# continue
# user_info = LdapService.user_info(uid)
# email = user_info.email_address
# emails.append(user_info.email_address)
# if not isinstance(email, str):
# raise ApiError(code="invalid_argument",
# message="The Email script requires at least 1 UID argument. The "
# "name of the variable in the task data that contains subject and"
# " user ids to process. This must point to an array or a string, but "
# "it currently points to a %s " % emails.__class__.__name__)
#
# return emails
return emails
def get_subject(self, task, args):
# subject = ''

View File

@ -377,6 +377,12 @@ class WorkflowProcessor(object):
except WorkflowTaskExecException as we:
raise ApiError.from_task("task_error", str(we), we.task)
def cancel_notify(self):
try:
self.bpmn_workflow.cancel_notify()
except WorkflowTaskExecException as we:
raise ApiError.from_task("task_error", str(we), we.task)
def serialize(self):
return self._serializer.serialize_workflow(self.bpmn_workflow,include_spec=True)