Run black on moto & test directories.

This commit is contained in:
Asher Foa 2019-10-31 08:44:26 -07:00
commit 96e5b1993d
507 changed files with 52541 additions and 47814 deletions

View file

@ -23,14 +23,10 @@ from .workflow_type import WorkflowType # noqa
from .workflow_execution import WorkflowExecution # noqa
from time import sleep
KNOWN_SWF_TYPES = {
"activity": ActivityType,
"workflow": WorkflowType,
}
KNOWN_SWF_TYPES = {"activity": ActivityType, "workflow": WorkflowType}
class SWFBackend(BaseBackend):
def __init__(self, region_name):
self.region_name = region_name
self.domains = []
@ -55,46 +51,53 @@ class SWFBackend(BaseBackend):
wfe._process_timeouts()
def list_domains(self, status, reverse_order=None):
domains = [domain for domain in self.domains
if domain.status == status]
domains = [domain for domain in self.domains if domain.status == status]
domains = sorted(domains, key=lambda domain: domain.name)
if reverse_order:
domains = reversed(domains)
return domains
def list_open_workflow_executions(self, domain_name, maximum_page_size,
tag_filter, reverse_order, **kwargs):
def list_open_workflow_executions(
self, domain_name, maximum_page_size, tag_filter, reverse_order, **kwargs
):
self._process_timeouts()
domain = self._get_domain(domain_name)
if domain.status == "DEPRECATED":
raise SWFDomainDeprecatedFault(domain_name)
open_wfes = [
wfe for wfe in domain.workflow_executions
if wfe.execution_status == 'OPEN'
wfe for wfe in domain.workflow_executions if wfe.execution_status == "OPEN"
]
if tag_filter:
for open_wfe in open_wfes:
if tag_filter['tag'] not in open_wfe.tag_list:
if tag_filter["tag"] not in open_wfe.tag_list:
open_wfes.remove(open_wfe)
if reverse_order:
open_wfes = reversed(open_wfes)
return open_wfes[0:maximum_page_size]
def list_closed_workflow_executions(self, domain_name, close_time_filter,
tag_filter, close_status_filter, maximum_page_size, reverse_order,
**kwargs):
def list_closed_workflow_executions(
self,
domain_name,
close_time_filter,
tag_filter,
close_status_filter,
maximum_page_size,
reverse_order,
**kwargs
):
self._process_timeouts()
domain = self._get_domain(domain_name)
if domain.status == "DEPRECATED":
raise SWFDomainDeprecatedFault(domain_name)
closed_wfes = [
wfe for wfe in domain.workflow_executions
if wfe.execution_status == 'CLOSED'
wfe
for wfe in domain.workflow_executions
if wfe.execution_status == "CLOSED"
]
if tag_filter:
for closed_wfe in closed_wfes:
if tag_filter['tag'] not in closed_wfe.tag_list:
if tag_filter["tag"] not in closed_wfe.tag_list:
closed_wfes.remove(closed_wfe)
if close_status_filter:
for closed_wfe in closed_wfes:
@ -104,12 +107,12 @@ class SWFBackend(BaseBackend):
closed_wfes = reversed(closed_wfes)
return closed_wfes[0:maximum_page_size]
def register_domain(self, name, workflow_execution_retention_period_in_days,
description=None):
def register_domain(
self, name, workflow_execution_retention_period_in_days, description=None
):
if self._get_domain(name, ignore_empty=True):
raise SWFDomainAlreadyExistsFault(name)
domain = Domain(name, workflow_execution_retention_period_in_days,
description)
domain = Domain(name, workflow_execution_retention_period_in_days, description)
self.domains.append(domain)
def deprecate_domain(self, name):
@ -149,15 +152,23 @@ class SWFBackend(BaseBackend):
domain = self._get_domain(domain_name)
return domain.get_type(kind, name, version)
def start_workflow_execution(self, domain_name, workflow_id,
workflow_name, workflow_version,
tag_list=None, input=None, **kwargs):
def start_workflow_execution(
self,
domain_name,
workflow_id,
workflow_name,
workflow_version,
tag_list=None,
input=None,
**kwargs
):
domain = self._get_domain(domain_name)
wf_type = domain.get_type("workflow", workflow_name, workflow_version)
if wf_type.status == "DEPRECATED":
raise SWFTypeDeprecatedFault(wf_type)
wfe = WorkflowExecution(domain, wf_type, workflow_id,
tag_list=tag_list, input=input, **kwargs)
wfe = WorkflowExecution(
domain, wf_type, workflow_id, tag_list=tag_list, input=input, **kwargs
)
domain.add_workflow_execution(wfe)
wfe.start()
@ -213,9 +224,9 @@ class SWFBackend(BaseBackend):
count += wfe.open_counts["openDecisionTasks"]
return count
def respond_decision_task_completed(self, task_token,
decisions=None,
execution_context=None):
def respond_decision_task_completed(
self, task_token, decisions=None, execution_context=None
):
# process timeouts on all objects
self._process_timeouts()
# let's find decision task
@ -244,14 +255,15 @@ class SWFBackend(BaseBackend):
"execution",
"WorkflowExecution=[workflowId={0}, runId={1}]".format(
wfe.workflow_id, wfe.run_id
)
),
)
# decision task found, but already completed
if decision_task.state != "STARTED":
if decision_task.state == "COMPLETED":
raise SWFUnknownResourceFault(
"decision task, scheduledEventId = {0}".format(
decision_task.scheduled_event_id)
decision_task.scheduled_event_id
)
)
else:
raise ValueError(
@ -263,9 +275,11 @@ class SWFBackend(BaseBackend):
# everything's good
if decision_task:
wfe = decision_task.workflow_execution
wfe.complete_decision_task(decision_task.task_token,
decisions=decisions,
execution_context=execution_context)
wfe.complete_decision_task(
decision_task.task_token,
decisions=decisions,
execution_context=execution_context,
)
def poll_for_activity_task(self, domain_name, task_list, identity=None):
# process timeouts on all objects
@ -308,8 +322,7 @@ class SWFBackend(BaseBackend):
count = 0
for _task_list, tasks in domain.activity_task_lists.items():
if _task_list == task_list:
pending = [t for t in tasks if t.state in [
"SCHEDULED", "STARTED"]]
pending = [t for t in tasks if t.state in ["SCHEDULED", "STARTED"]]
count += len(pending)
return count
@ -333,14 +346,15 @@ class SWFBackend(BaseBackend):
"execution",
"WorkflowExecution=[workflowId={0}, runId={1}]".format(
wfe.workflow_id, wfe.run_id
)
),
)
# activity task found, but already completed
if activity_task.state != "STARTED":
if activity_task.state == "COMPLETED":
raise SWFUnknownResourceFault(
"activity, scheduledEventId = {0}".format(
activity_task.scheduled_event_id)
activity_task.scheduled_event_id
)
)
else:
raise ValueError(
@ -364,18 +378,24 @@ class SWFBackend(BaseBackend):
self._process_timeouts()
activity_task = self._find_activity_task_from_token(task_token)
wfe = activity_task.workflow_execution
wfe.fail_activity_task(activity_task.task_token,
reason=reason, details=details)
wfe.fail_activity_task(activity_task.task_token, reason=reason, details=details)
def terminate_workflow_execution(self, domain_name, workflow_id, child_policy=None,
details=None, reason=None, run_id=None):
def terminate_workflow_execution(
self,
domain_name,
workflow_id,
child_policy=None,
details=None,
reason=None,
run_id=None,
):
# process timeouts on all objects
self._process_timeouts()
domain = self._get_domain(domain_name)
wfe = domain.get_workflow_execution(
workflow_id, run_id=run_id, raise_if_closed=True)
wfe.terminate(child_policy=child_policy,
details=details, reason=reason)
workflow_id, run_id=run_id, raise_if_closed=True
)
wfe.terminate(child_policy=child_policy, details=details, reason=reason)
def record_activity_task_heartbeat(self, task_token, details=None):
# process timeouts on all objects
@ -385,12 +405,15 @@ class SWFBackend(BaseBackend):
if details:
activity_task.details = details
def signal_workflow_execution(self, domain_name, signal_name, workflow_id, input=None, run_id=None):
def signal_workflow_execution(
self, domain_name, signal_name, workflow_id, input=None, run_id=None
):
# process timeouts on all objects
self._process_timeouts()
domain = self._get_domain(domain_name)
wfe = domain.get_workflow_execution(
workflow_id, run_id=run_id, raise_if_closed=True)
workflow_id, run_id=run_id, raise_if_closed=True
)
wfe.signal(signal_name, input)

View file

@ -10,9 +10,15 @@ from .timeout import Timeout
class ActivityTask(BaseModel):
def __init__(self, activity_id, activity_type, scheduled_event_id,
workflow_execution, timeouts, input=None):
def __init__(
self,
activity_id,
activity_type,
scheduled_event_id,
workflow_execution,
timeouts,
input=None,
):
self.activity_id = activity_id
self.activity_type = activity_type
self.details = None
@ -68,8 +74,9 @@ class ActivityTask(BaseModel):
if not self.open or not self.workflow_execution.open:
return None
# TODO: handle the "NONE" case
heartbeat_timeout_at = (self.last_heartbeat_timestamp +
int(self.timeouts["heartbeatTimeout"]))
heartbeat_timeout_at = self.last_heartbeat_timestamp + int(
self.timeouts["heartbeatTimeout"]
)
_timeout = Timeout(self, heartbeat_timeout_at, "HEARTBEAT")
if _timeout.reached:
return _timeout

View file

@ -2,7 +2,6 @@ from .generic_type import GenericType
class ActivityType(GenericType):
@property
def _configuration_keys(self):
return [

View file

@ -10,7 +10,6 @@ from .timeout import Timeout
class DecisionTask(BaseModel):
def __init__(self, workflow_execution, scheduled_event_id):
self.workflow_execution = workflow_execution
self.workflow_type = workflow_execution.workflow_type
@ -19,7 +18,9 @@ class DecisionTask(BaseModel):
self.previous_started_event_id = 0
self.started_event_id = None
self.started_timestamp = None
self.start_to_close_timeout = self.workflow_execution.task_start_to_close_timeout
self.start_to_close_timeout = (
self.workflow_execution.task_start_to_close_timeout
)
self.state = "SCHEDULED"
# this is *not* necessarily coherent with workflow execution history,
# but that shouldn't be a problem for tests
@ -37,9 +38,7 @@ class DecisionTask(BaseModel):
def to_full_dict(self, reverse_order=False):
events = self.workflow_execution.events(reverse_order=reverse_order)
hsh = {
"events": [
evt.to_dict() for evt in events
],
"events": [evt.to_dict() for evt in events],
"taskToken": self.task_token,
"previousStartedEventId": self.previous_started_event_id,
"workflowExecution": self.workflow_execution.to_short_dict(),
@ -62,8 +61,7 @@ class DecisionTask(BaseModel):
if not self.started or not self.workflow_execution.open:
return None
# TODO: handle the "NONE" case
start_to_close_at = self.started_timestamp + \
int(self.start_to_close_timeout)
start_to_close_at = self.started_timestamp + int(self.start_to_close_timeout)
_timeout = Timeout(self, start_to_close_at, "START_TO_CLOSE")
if _timeout.reached:
return _timeout

View file

@ -9,16 +9,12 @@ from ..exceptions import (
class Domain(BaseModel):
def __init__(self, name, retention, description=None):
self.name = name
self.retention = retention
self.description = description
self.status = "REGISTERED"
self.types = {
"activity": defaultdict(dict),
"workflow": defaultdict(dict),
}
self.types = {"activity": defaultdict(dict), "workflow": defaultdict(dict)}
# Workflow executions have an id, which unicity is guaranteed
# at domain level (not super clear in the docs, but I checked
# that against SWF API) ; hence the storage method as a dict
@ -32,10 +28,7 @@ class Domain(BaseModel):
return "Domain(name: %(name)s, status: %(status)s)" % self.__dict__
def to_short_dict(self):
hsh = {
"name": self.name,
"status": self.status,
}
hsh = {"name": self.name, "status": self.status}
if self.description:
hsh["description"] = self.description
return hsh
@ -43,9 +36,7 @@ class Domain(BaseModel):
def to_full_dict(self):
return {
"domainInfo": self.to_short_dict(),
"configuration": {
"workflowExecutionRetentionPeriodInDays": self.retention,
}
"configuration": {"workflowExecutionRetentionPeriodInDays": self.retention},
}
def get_type(self, kind, name, version, ignore_empty=False):
@ -57,7 +48,7 @@ class Domain(BaseModel):
"type",
"{0}Type=[name={1}, version={2}]".format(
kind.capitalize(), name, version
)
),
)
def add_type(self, _type):
@ -77,15 +68,22 @@ class Domain(BaseModel):
raise SWFWorkflowExecutionAlreadyStartedFault()
self.workflow_executions.append(workflow_execution)
def get_workflow_execution(self, workflow_id, run_id=None,
raise_if_none=True, raise_if_closed=False):
def get_workflow_execution(
self, workflow_id, run_id=None, raise_if_none=True, raise_if_closed=False
):
# query
if run_id:
_all = [w for w in self.workflow_executions
if w.workflow_id == workflow_id and w.run_id == run_id]
_all = [
w
for w in self.workflow_executions
if w.workflow_id == workflow_id and w.run_id == run_id
]
else:
_all = [w for w in self.workflow_executions
if w.workflow_id == workflow_id and w.open]
_all = [
w
for w in self.workflow_executions
if w.workflow_id == workflow_id and w.open
]
# reduce
wfe = _all[0] if _all else None
# raise if closed / none
@ -93,8 +91,12 @@ class Domain(BaseModel):
wfe = None
if not wfe and raise_if_none:
if run_id:
args = ["execution", "WorkflowExecution=[workflowId={0}, runId={1}]".format(
workflow_id, run_id)]
args = [
"execution",
"WorkflowExecution=[workflowId={0}, runId={1}]".format(
workflow_id, run_id
),
]
else:
args = ["execution, workflowId = {0}".format(workflow_id)]
raise SWFUnknownResourceFault(*args)

View file

@ -5,7 +5,6 @@ from moto.core.utils import camelcase_to_underscores
class GenericType(BaseModel):
def __init__(self, name, version, **kwargs):
self.name = name
self.version = version
@ -24,7 +23,9 @@ class GenericType(BaseModel):
def __repr__(self):
cls = self.__class__.__name__
attrs = "name: %(name)s, version: %(version)s, status: %(status)s" % self.__dict__
attrs = (
"name: %(name)s, version: %(version)s, status: %(status)s" % self.__dict__
)
return "{0}({1})".format(cls, attrs)
@property
@ -36,10 +37,7 @@ class GenericType(BaseModel):
raise NotImplementedError()
def to_short_dict(self):
return {
"name": self.name,
"version": self.version,
}
return {"name": self.name, "version": self.version}
def to_medium_dict(self):
hsh = {
@ -54,10 +52,7 @@ class GenericType(BaseModel):
return hsh
def to_full_dict(self):
hsh = {
"typeInfo": self.to_medium_dict(),
"configuration": {}
}
hsh = {"typeInfo": self.to_medium_dict(), "configuration": {}}
if self.task_list:
hsh["configuration"]["defaultTaskList"] = {"name": self.task_list}
for key in self._configuration_keys:

View file

@ -25,17 +25,17 @@ SUPPORTED_HISTORY_EVENT_TYPES = (
"ActivityTaskTimedOut",
"DecisionTaskTimedOut",
"WorkflowExecutionTimedOut",
"WorkflowExecutionSignaled"
"WorkflowExecutionSignaled",
)
class HistoryEvent(BaseModel):
def __init__(self, event_id, event_type, event_timestamp=None, **kwargs):
if event_type not in SUPPORTED_HISTORY_EVENT_TYPES:
raise NotImplementedError(
"HistoryEvent does not implement attributes for type '{0}'".format(
event_type)
event_type
)
)
self.event_id = event_id
self.event_type = event_type
@ -61,7 +61,7 @@ class HistoryEvent(BaseModel):
"eventId": self.event_id,
"eventType": self.event_type,
"eventTimestamp": self.event_timestamp,
self._attributes_key(): self.event_attributes
self._attributes_key(): self.event_attributes,
}
def _attributes_key(self):

View file

@ -3,7 +3,6 @@ from moto.core.utils import unix_time
class Timeout(BaseModel):
def __init__(self, obj, timestamp, kind):
self.obj = obj
self.timestamp = timestamp

View file

@ -4,9 +4,7 @@ import uuid
from moto.core import BaseModel
from moto.core.utils import camelcase_to_underscores, unix_time
from ..constants import (
DECISIONS_FIELDS,
)
from ..constants import DECISIONS_FIELDS
from ..exceptions import (
SWFDefaultUndefinedFault,
SWFValidationException,
@ -38,7 +36,7 @@ class WorkflowExecution(BaseModel):
"FailWorkflowExecution",
"RequestCancelActivityTask",
"StartChildWorkflowExecution",
"CancelWorkflowExecution"
"CancelWorkflowExecution",
]
def __init__(self, domain, workflow_type, workflow_id, **kwargs):
@ -66,11 +64,10 @@ class WorkflowExecution(BaseModel):
# param is set, # SWF will raise DefaultUndefinedFault errors in the
# same order as the few lines that follow)
self._set_from_kwargs_or_workflow_type(
kwargs, "execution_start_to_close_timeout")
self._set_from_kwargs_or_workflow_type(
kwargs, "task_list", "task_list")
self._set_from_kwargs_or_workflow_type(
kwargs, "task_start_to_close_timeout")
kwargs, "execution_start_to_close_timeout"
)
self._set_from_kwargs_or_workflow_type(kwargs, "task_list", "task_list")
self._set_from_kwargs_or_workflow_type(kwargs, "task_start_to_close_timeout")
self._set_from_kwargs_or_workflow_type(kwargs, "child_policy")
self.input = kwargs.get("input")
# counters
@ -89,7 +86,9 @@ class WorkflowExecution(BaseModel):
def __repr__(self):
return "WorkflowExecution(run_id: {0})".format(self.run_id)
def _set_from_kwargs_or_workflow_type(self, kwargs, local_key, workflow_type_key=None):
def _set_from_kwargs_or_workflow_type(
self, kwargs, local_key, workflow_type_key=None
):
if workflow_type_key is None:
workflow_type_key = "default_" + local_key
value = kwargs.get(local_key)
@ -109,10 +108,7 @@ class WorkflowExecution(BaseModel):
]
def to_short_dict(self):
return {
"workflowId": self.workflow_id,
"runId": self.run_id
}
return {"workflowId": self.workflow_id, "runId": self.run_id}
def to_medium_dict(self):
hsh = {
@ -129,9 +125,7 @@ class WorkflowExecution(BaseModel):
def to_full_dict(self):
hsh = {
"executionInfo": self.to_medium_dict(),
"executionConfiguration": {
"taskList": {"name": self.task_list}
}
"executionConfiguration": {"taskList": {"name": self.task_list}},
}
# configuration
for key in self._configuration_keys:
@ -152,23 +146,20 @@ class WorkflowExecution(BaseModel):
def to_list_dict(self):
hsh = {
'execution': {
'workflowId': self.workflow_id,
'runId': self.run_id,
},
'workflowType': self.workflow_type.to_short_dict(),
'startTimestamp': self.start_timestamp,
'executionStatus': self.execution_status,
'cancelRequested': self.cancel_requested,
"execution": {"workflowId": self.workflow_id, "runId": self.run_id},
"workflowType": self.workflow_type.to_short_dict(),
"startTimestamp": self.start_timestamp,
"executionStatus": self.execution_status,
"cancelRequested": self.cancel_requested,
}
if self.tag_list:
hsh['tagList'] = self.tag_list
hsh["tagList"] = self.tag_list
if self.parent:
hsh['parent'] = self.parent
hsh["parent"] = self.parent
if self.close_status:
hsh['closeStatus'] = self.close_status
hsh["closeStatus"] = self.close_status
if self.close_timestamp:
hsh['closeTimestamp'] = self.close_timestamp
hsh["closeTimestamp"] = self.close_timestamp
return hsh
def _process_timeouts(self):
@ -206,10 +197,7 @@ class WorkflowExecution(BaseModel):
# now find the first timeout to process
first_timeout = None
if timeout_candidates:
first_timeout = min(
timeout_candidates,
key=lambda t: t.timestamp
)
first_timeout = min(timeout_candidates, key=lambda t: t.timestamp)
if first_timeout:
should_schedule_decision_next = False
@ -258,7 +246,7 @@ class WorkflowExecution(BaseModel):
task_list=self.task_list,
task_start_to_close_timeout=self.task_start_to_close_timeout,
workflow_type=self.workflow_type,
input=self.input
input=self.input,
)
self.schedule_decision_task()
@ -269,8 +257,7 @@ class WorkflowExecution(BaseModel):
task_list=self.task_list,
)
self.domain.add_to_decision_task_list(
self.task_list,
DecisionTask(self, evt.event_id),
self.task_list, DecisionTask(self, evt.event_id)
)
self.open_counts["openDecisionTasks"] += 1
@ -285,32 +272,30 @@ class WorkflowExecution(BaseModel):
@property
def decision_tasks(self):
return [t for t in self.domain.decision_tasks
if t.workflow_execution == self]
return [t for t in self.domain.decision_tasks if t.workflow_execution == self]
@property
def activity_tasks(self):
return [t for t in self.domain.activity_tasks
if t.workflow_execution == self]
return [t for t in self.domain.activity_tasks if t.workflow_execution == self]
def _find_decision_task(self, task_token):
for dt in self.decision_tasks:
if dt.task_token == task_token:
return dt
raise ValueError(
"No decision task with token: {0}".format(task_token)
)
raise ValueError("No decision task with token: {0}".format(task_token))
def start_decision_task(self, task_token, identity=None):
dt = self._find_decision_task(task_token)
evt = self._add_event(
"DecisionTaskStarted",
scheduled_event_id=dt.scheduled_event_id,
identity=identity
identity=identity,
)
dt.start(evt.event_id)
def complete_decision_task(self, task_token, decisions=None, execution_context=None):
def complete_decision_task(
self, task_token, decisions=None, execution_context=None
):
# 'decisions' can be None per boto.swf defaults, so replace it with something iterable
if not decisions:
decisions = []
@ -336,12 +321,14 @@ class WorkflowExecution(BaseModel):
constraints = DECISIONS_FIELDS.get(kind, {})
for key, constraint in constraints.items():
if constraint["required"] and not value.get(key):
problems.append({
"type": "null_value",
"where": "decisions.{0}.member.{1}.{2}".format(
decision_id, kind, key
)
})
problems.append(
{
"type": "null_value",
"where": "decisions.{0}.member.{1}.{2}".format(
decision_id, kind, key
),
}
)
return problems
def validate_decisions(self, decisions):
@ -362,9 +349,7 @@ class WorkflowExecution(BaseModel):
"CancelWorkflowExecution",
]
if dcs["decisionType"] in close_decision_types:
raise SWFValidationException(
"Close must be last decision in list"
)
raise SWFValidationException("Close must be last decision in list")
decision_number = 0
for dcs in decisions:
@ -372,24 +357,29 @@ class WorkflowExecution(BaseModel):
# check decision types mandatory attributes
# NB: the real SWF service seems to check attributes even for attributes list
# that are not in line with the decisionType, so we do the same
attrs_to_check = [
d for d in dcs.keys() if d.endswith("DecisionAttributes")]
attrs_to_check = [d for d in dcs.keys() if d.endswith("DecisionAttributes")]
if dcs["decisionType"] in self.KNOWN_DECISION_TYPES:
decision_type = dcs["decisionType"]
decision_attr = "{0}DecisionAttributes".format(
decapitalize(decision_type))
decapitalize(decision_type)
)
attrs_to_check.append(decision_attr)
for attr in attrs_to_check:
problems += self._check_decision_attributes(
attr, dcs.get(attr, {}), decision_number)
attr, dcs.get(attr, {}), decision_number
)
# check decision type is correct
if dcs["decisionType"] not in self.KNOWN_DECISION_TYPES:
problems.append({
"type": "bad_decision_type",
"value": dcs["decisionType"],
"where": "decisions.{0}.member.decisionType".format(decision_number),
"possible_values": ", ".join(self.KNOWN_DECISION_TYPES),
})
problems.append(
{
"type": "bad_decision_type",
"value": dcs["decisionType"],
"where": "decisions.{0}.member.decisionType".format(
decision_number
),
"possible_values": ", ".join(self.KNOWN_DECISION_TYPES),
}
)
# raise if any problem
if any(problems):
@ -403,14 +393,12 @@ class WorkflowExecution(BaseModel):
# handle each decision separately, in order
for decision in decisions:
decision_type = decision["decisionType"]
attributes_key = "{0}DecisionAttributes".format(
decapitalize(decision_type))
attributes_key = "{0}DecisionAttributes".format(decapitalize(decision_type))
attributes = decision.get(attributes_key, {})
if decision_type == "CompleteWorkflowExecution":
self.complete(event_id, attributes.get("result"))
elif decision_type == "FailWorkflowExecution":
self.fail(event_id, attributes.get(
"details"), attributes.get("reason"))
self.fail(event_id, attributes.get("details"), attributes.get("reason"))
elif decision_type == "ScheduleActivityTask":
self.schedule_activity_task(event_id, attributes)
else:
@ -425,7 +413,8 @@ class WorkflowExecution(BaseModel):
# TODO: implement Decision type: StartChildWorkflowExecution
# TODO: implement Decision type: StartTimer
raise NotImplementedError(
"Cannot handle decision: {0}".format(decision_type))
"Cannot handle decision: {0}".format(decision_type)
)
# finally decrement counter if and only if everything went well
self.open_counts["openDecisionTasks"] -= 1
@ -475,18 +464,21 @@ class WorkflowExecution(BaseModel):
ignore_empty=True,
)
if not activity_type:
fake_type = ActivityType(attributes["activityType"]["name"],
attributes["activityType"]["version"])
fail_schedule_activity_task(fake_type,
"ACTIVITY_TYPE_DOES_NOT_EXIST")
fake_type = ActivityType(
attributes["activityType"]["name"],
attributes["activityType"]["version"],
)
fail_schedule_activity_task(fake_type, "ACTIVITY_TYPE_DOES_NOT_EXIST")
return
if activity_type.status == "DEPRECATED":
fail_schedule_activity_task(activity_type,
"ACTIVITY_TYPE_DEPRECATED")
fail_schedule_activity_task(activity_type, "ACTIVITY_TYPE_DEPRECATED")
return
if any(at for at in self.activity_tasks if at.activity_id == attributes["activityId"]):
fail_schedule_activity_task(activity_type,
"ACTIVITY_ID_ALREADY_IN_USE")
if any(
at
for at in self.activity_tasks
if at.activity_id == attributes["activityId"]
):
fail_schedule_activity_task(activity_type, "ACTIVITY_ID_ALREADY_IN_USE")
return
# find task list or default task list, else fail
@ -494,20 +486,25 @@ class WorkflowExecution(BaseModel):
if not task_list and activity_type.task_list:
task_list = activity_type.task_list
if not task_list:
fail_schedule_activity_task(activity_type,
"DEFAULT_TASK_LIST_UNDEFINED")
fail_schedule_activity_task(activity_type, "DEFAULT_TASK_LIST_UNDEFINED")
return
# find timeouts or default timeout, else fail
timeouts = {}
for _type in ["scheduleToStartTimeout", "scheduleToCloseTimeout", "startToCloseTimeout", "heartbeatTimeout"]:
for _type in [
"scheduleToStartTimeout",
"scheduleToCloseTimeout",
"startToCloseTimeout",
"heartbeatTimeout",
]:
default_key = "default_task_" + camelcase_to_underscores(_type)
default_value = getattr(activity_type, default_key)
timeouts[_type] = attributes.get(_type, default_value)
if not timeouts[_type]:
error_key = default_key.replace("default_task_", "default_")
fail_schedule_activity_task(activity_type,
"{0}_UNDEFINED".format(error_key.upper()))
fail_schedule_activity_task(
activity_type, "{0}_UNDEFINED".format(error_key.upper())
)
return
# Only add event and increment counters now that nothing went wrong
@ -541,16 +538,14 @@ class WorkflowExecution(BaseModel):
for task in self.activity_tasks:
if task.task_token == task_token:
return task
raise ValueError(
"No activity task with token: {0}".format(task_token)
)
raise ValueError("No activity task with token: {0}".format(task_token))
def start_activity_task(self, task_token, identity=None):
task = self._find_activity_task(task_token)
evt = self._add_event(
"ActivityTaskStarted",
scheduled_event_id=task.scheduled_event_id,
identity=identity
identity=identity,
)
task.start(evt.event_id)
@ -601,17 +596,16 @@ class WorkflowExecution(BaseModel):
def signal(self, signal_name, input):
self._add_event(
"WorkflowExecutionSignaled",
signal_name=signal_name,
input=input,
"WorkflowExecutionSignaled", signal_name=signal_name, input=input
)
self.schedule_decision_task()
def first_timeout(self):
if not self.open or not self.start_timestamp:
return None
start_to_close_at = self.start_timestamp + \
int(self.execution_start_to_close_timeout)
start_to_close_at = self.start_timestamp + int(
self.execution_start_to_close_timeout
)
_timeout = Timeout(self, start_to_close_at, "START_TO_CLOSE")
if _timeout.reached:
return _timeout

View file

@ -2,7 +2,6 @@ from .generic_type import GenericType
class WorkflowType(GenericType):
@property
def _configuration_keys(self):
return [