def cancel(self, task_token, details=None): """Responds to ``swf`` that the activity task was canceled :param task_token: canceled activity task token :type task_token: string :param details: provided details about cancel :type details: string """ try: return self.connection.respond_activity_task_canceled( task_token, details=format.details(details), ) except boto.exception.SWFResponseError as e: message = self.get_error_message(e) if e.error_code == 'UnknownResourceFault': raise DoesNotExistError( "Unable to cancel activity task with token={}".format( task_token), message, ) raise ResponseError(message) finally: logging_context.reset()
def _diff(self): """Checks for differences between Domain instance and upstream version :returns: A list of swf.models.base.ModelDiff namedtuple describing differences :rtype: list """ try: description = self.connection.describe_domain(self.name) except SWFResponseError as e: if e.error_code == 'UnknownResourceFault': raise DoesNotExistError("Remote Domain does not exist") raise ResponseError(e.body['message']) domain_info = description['domainInfo'] domain_config = description['configuration'] return ModelDiff( ('name', self.name, domain_info['name']), ('status', self.status, domain_info['status']), ('description', self.description, domain_info.get('description')), ('retention_period', self.retention_period, domain_config['workflowExecutionRetentionPeriodInDays']), )
def save(self): """Creates the activity type amazon side""" try: self.connection.register_activity_type( self.domain.name, self.name, self.version, task_list=str(self.task_list), default_task_heartbeat_timeout=str( self.task_heartbeat_timeout), default_task_schedule_to_close_timeout=str( self.task_schedule_to_close_timeout), default_task_schedule_to_start_timeout=str( self.task_schedule_to_start_timeout), default_task_start_to_close_timeout=str( self.task_start_to_close_timeout), description=self.description) except SWFTypeAlreadyExistsError as err: raise AlreadyExistsError('{} already exists'.format(self)) except SWFResponseError as err: if err.error_code in [ 'UnknownResourceFault', 'TypeDeprecatedFault' ]: raise DoesNotExistError(err.body['message']) raise
def complete(self, task_token, decisions=None, execution_context=None): """Responds to ``swf`` decisions have been made about the task with `task_token`` :param task_token: completed decision task token :type task_token: str :param decisions: The list of decisions (possibly empty) made by the decider while processing this decision task :type decisions: list[swf.models.decision.base.Decision] :param execution_context: User-defined context to add to workflow execution. :type execution_context: str """ try: self.connection.respond_decision_task_completed( task_token, decisions, execution_context, ) except boto.exception.SWFResponseError as e: if e.error_code == 'UnknownResourceFault': raise DoesNotExistError( "Unable to complete decision task with token={}".format( task_token), e.body['message'], ) raise ResponseError(e.body['message'])
def heartbeat(self, task_token, details=None): """Records activity task heartbeat :param task_token: canceled activity task token :type task_token: str :param details: provided details about task progress :type details: string """ try: return self.connection.record_activity_task_heartbeat( task_token, format.heartbeat_details(details), ) except boto.exception.SWFResponseError as e: message = self.get_error_message(e) if e.error_code == "UnknownResourceFault": raise DoesNotExistError( "Unable to send heartbeat with token={}".format(task_token), message, ) if e.error_code == "ThrottlingException": raise RateLimitExceededError( "Rate exceeded when sending heartbeat with token={}".format( task_token ), message, ) raise ResponseError(message)
def complete(self, task_token, decisions=None, execution_context=None): """Responds to ``swf`` decisions have been made about the task with `task_token`` :param task_token: completed decision task token :type task_token: str :param decisions: The list of decisions (possibly empty) made by the decider while processing this decision task :type decisions: list[swf.models.decision.base.Decision] :param execution_context: User-defined context to add to workflow execution. :type execution_context: str """ if execution_context is not None and not isinstance( execution_context, compat.string_types): execution_context = json_dumps(execution_context) try: self.connection.respond_decision_task_completed( task_token, decisions, format.execution_context(execution_context), ) except boto.exception.SWFResponseError as e: message = self.get_error_message(e) if e.error_code == 'UnknownResourceFault': raise DoesNotExistError( "Unable to complete decision task with token={}".format( task_token), message, ) raise ResponseError(message) finally: logging_context.reset()
def _diff(self): """Checks for differences between Domain instance and upstream version :returns: A swf.models.base.ModelDiff describing differences :rtype: ModelDiff """ try: description = self.connection.describe_domain(self.name) except SWFResponseError as e: if e.error_code == "UnknownResourceFault": raise DoesNotExistError("Remote Domain does not exist") raise ResponseError(e.body["message"]) domain_info = description["domainInfo"] domain_config = description["configuration"] return ModelDiff( ("name", self.name, domain_info["name"]), ("status", self.status, domain_info["status"]), ("description", self.description, domain_info.get("description")), ( "retention_period", self.retention_period, domain_config["workflowExecutionRetentionPeriodInDays"], ), )
def fail(self, task_token, details=None, reason=None): """Replies to ``swf`` that the activity task failed :param task_token: canceled activity task token :type task_token: string :param details: provided details about the failure :type details: string :param reason: Description of the error that may assist in diagnostics :type reason: string """ try: return self.connection.respond_activity_task_failed( task_token, details=format.details(details), reason=format.reason(reason), ) except boto.exception.SWFResponseError as e: message = self.get_error_message(e) if e.error_code == "UnknownResourceFault": raise DoesNotExistError( "Unable to fail activity task with token={}".format(task_token), message, ) raise ResponseError(message)
def _diff(self): """Checks for differences between WorkflowType instance and upstream version :returns: A swf.models.base.ModelDiff describing differences :rtype: ModelDiff """ try: description = self.connection.describe_workflow_type( self.domain.name, self.name, self.version ) except SWFResponseError as e: if e.error_code == 'UnknownResourceFault': raise DoesNotExistError("Remote Domain does not exist") raise ResponseError(e.body['message']) workflow_info = description['typeInfo'] workflow_config = description['configuration'] return ModelDiff( ('name', self.name, workflow_info['workflowType']['name']), ('version', self.version, workflow_info['workflowType']['version']), ('status', self.status, workflow_info['status']), ('creation_date', self.creation_date, workflow_info['creationDate']), ('deprecation_date', self.deprecation_date, workflow_info['deprecationDate']), ('task_list', self.task_list, workflow_config['defaultTaskList']['name']), ('child_policy', self.child_policy, workflow_config['defaultChildPolicy']), ('execution_timeout', self.execution_timeout, workflow_config['defaultExecutionStartToCloseTimeout']), ('decision_tasks_timout', self.decision_tasks_timeout, workflow_config['defaultTaskStartToCloseTimeout']), ('description', self.description, workflow_info['description']), )
def delete(self): """Deprecates the workflow type amazon-side""" try: self.connection.deprecate_workflow_type(self.domain.name, self.name, self.version) except SWFResponseError as e: if e.error_code in ['UnknownResourceFault', 'TypeDeprecatedFault']: raise DoesNotExistError(e.body['message'])
def get(self, workflow_id, run_id, *args, **kwargs): """ """ try: response = self.connection.describe_workflow_execution( self.domain.name, run_id, workflow_id ) except SWFResponseError as e: if e.error_code == "UnknownResourceFault": raise DoesNotExistError(e.body["message"]) raise ResponseError(e.body["message"]) execution_info = response[self._infos] execution_config = response["executionConfiguration"] return self.to_WorkflowExecution( self.domain, execution_info, task_list=get_subkey(execution_config, ["taskList", "name"]), child_policy=execution_config.get("childPolicy"), execution_timeout=execution_config.get("executionStartToCloseTimeout"), decision_tasks_timeout=execution_config.get("taskStartToCloseTimeout"), latest_activity_task_timestamp=response.get("latestActivityTaskTimestamp"), latest_execution_context=response.get("latestExecutionContext"), open_counts=response["openCounts"], )
def _diff(self): """Checks for differences between WorkflowExecution instance and upstream version :returns: A swf.models.base.ModelDiff describing differences :rtype: ModelDiff """ try: description = self.connection.describe_workflow_execution( self.domain.name, self.run_id, self.workflow_id ) except SWFResponseError as e: if e.error_code == 'UnknownResourceFault': raise DoesNotExistError("Remote Domain does not exist") raise ResponseError(e.body['message']) execution_info = description['executionInfo'] execution_config = description['executionConfiguration'] return ModelDiff( ('workflow_id', self.workflow_id, execution_info['execution']['workflowId']), ('run_id', self.run_id, execution_info['execution']['runId']), ('status', self.status, execution_info['executionStatus']), ('task_list', self.task_list, execution_config['taskList']['name']), ('child_policy', self.child_policy, execution_config['childPolicy']), ('execution_timeout', self.execution_timeout, execution_config['executionStartToCloseTimeout']), ('tag_list', self.tag_list, execution_info.get('tagList')), ('decision_tasks_timeout', self.decision_tasks_timeout, execution_config['taskStartToCloseTimeout']), )
def test_get_or_create_non_existent_domain(self): with patch.object(Layer1, 'describe_domain') as mock: mock.side_effect = DoesNotExistError("Mocked exception") with patch.object(Layer1, 'register_domain', mock_describe_domain): domain = self.qs.get_or_create("TestDomain") self.assertIsInstance(domain, Domain)
def test_get_or_create_non_existent_workflow_type(self): with patch.object(Layer1, 'describe_workflow_type') as mock: mock.side_effect = DoesNotExistError("Mocked exception") with patch.object(Layer1, 'register_workflow_type', mock_describe_workflow_type): workflow_type = self.wtq.get_or_create("TestDomain", "testversion") self.assertIsInstance(workflow_type, WorkflowType)
def test_get_or_create_non_existent_activity_type(self): with patch.object(Layer1, "describe_activity_type") as mock: mock.side_effect = DoesNotExistError("Mocked exception") with patch.object(Layer1, "register_activity_type", mock_describe_activity_type): activity_type = self.atq.get_or_create("TestDomain", "testversion") self.assertIsInstance(activity_type, ActivityType)
def poll(self, task_list=None, identity=None): """Polls for an activity task to process from current actor's instance defined ``task_list`` if no activity task was polled, raises a PollTimeout exception. :param task_list: task list the Actor should watch for tasks on :type task_list: string :param identity: Identity of the worker making the request, which is recorded in the ActivityTaskStarted event in the workflow history. This enables diagnostic tracing when problems arise. The form of this identity is user defined. :type identity: string :raises: PollTimeout :returns: task token, polled activity task :rtype: (str, ActivityTask) """ logging_context.reset() task_list = task_list or self.task_list identity = identity or self._identity try: task = self.connection.poll_for_activity_task( self.domain.name, task_list, identity=format.identity(identity), ) except boto.exception.SWFResponseError as e: message = self.get_error_message(e) if e.error_code == "UnknownResourceFault": raise DoesNotExistError( "Unable to poll activity task", message, ) raise ResponseError(message) if not task.get("taskToken"): raise PollTimeout("Activity Worker poll timed out") logging_context.set("workflow_id", task["workflowExecution"]["workflowId"]) logging_context.set("task_type", "activity") logging_context.set("event_id", task["startedEventId"]) logging_context.set("activity_id", task["activityId"]) activity_task = ActivityTask.from_poll(self.domain, self.task_list, task,) return Response( task_token=activity_task.task_token, activity_task=activity_task, raw_response=task, )
def _diff(self): """Checks for differences between ActivityType instance and upstream version :returns: A list (swf.models.base.ModelDiff) namedtuple describing differences :rtype: ModelDiff """ try: description = self.connection.describe_activity_type( self.domain.name, self.name, self.version) except SWFResponseError as err: if err.error_code == "UnknownResourceFault": raise DoesNotExistError("Remote ActivityType does not exist") raise ResponseError(err.body["message"]) info = description["typeInfo"] config = description["configuration"] return ModelDiff( ("name", self.name, info["activityType"]["name"]), ("version", self.version, info["activityType"]["version"]), ("status", self.status, info["status"]), ("description", self.description, info["description"]), ("creation_date", self.creation_date, info["creationDate"]), ("deprecation_date", self.deprecation_date, info["deprecationDate"]), ("task_list", self.task_list, config["defaultTaskList"]["name"]), ( "task_heartbeat_timeout", self.task_heartbeat_timeout, config["defaultTaskHeartbeatTimeout"], ), ( "task_schedule_to_close_timeout", self.task_schedule_to_close_timeout, config["defaultTaskScheduleToCloseTimeout"], ), ( "task_schedule_to_start_timeout", self.task_schedule_to_start_timeout, config["defaultTaskScheduleToStartTimeout"], ), ( "task_start_to_close_timeout", self.task_start_to_close_timeout, config["defaultTaskStartToCloseTimeout"], ), )
def _diff(self): """Checks for differences between WorkflowType instance and upstream version :returns: A swf.models.base.ModelDiff describing differences :rtype: ModelDiff """ try: description = self.connection.describe_workflow_type( self.domain.name, self.name, self.version) except SWFResponseError as e: if e.error_code == "UnknownResourceFault": raise DoesNotExistError("Remote Domain does not exist") raise ResponseError(e.body["message"]) workflow_info = description["typeInfo"] workflow_config = description["configuration"] return ModelDiff( ("name", self.name, workflow_info["workflowType"]["name"]), ("version", self.version, workflow_info["workflowType"]["version"]), ("status", self.status, workflow_info["status"]), ("creation_date", self.creation_date, workflow_info["creationDate"]), ( "deprecation_date", self.deprecation_date, workflow_info["deprecationDate"], ), ("task_list", self.task_list, workflow_config["defaultTaskList"]["name"]), ("child_policy", self.child_policy, workflow_config["defaultChildPolicy"]), ( "execution_timeout", self.execution_timeout, workflow_config["defaultExecutionStartToCloseTimeout"], ), ( "decision_tasks_timout", self.decision_tasks_timeout, workflow_config["defaultTaskStartToCloseTimeout"], ), ("description", self.description, workflow_info["description"]), )
def poll(self, task_list=None, identity=None): """Polls for an activity task to process from current actor's instance defined ``task_list`` if no activity task was polled, raises a PollTimeout exception. :param task_list: task list the Actor should watch for tasks on :type task_list: string :param identity: Identity of the worker making the request, which is recorded in the ActivityTaskStarted event in the workflow history. This enables diagnostic tracing when problems arise. The form of this identity is user defined. :type identity: string :raises: PollTimeout :returns: task token, polled activity task :rtype: (str, ActivityTask) """ task_list = task_list or self.task_list identity = identity or self._identity try: polled_activity_data = self.connection.poll_for_activity_task( self.domain.name, task_list, identity=identity) except boto.exception.SWFResponseError as e: message = self.get_error_message(e) if e.error_code == 'UnknownResourceFault': raise DoesNotExistError( "Unable to poll activity task", message, ) raise ResponseError(message) if 'taskToken' not in polled_activity_data: raise PollTimeout("Activity Worker poll timed out") activity_task = ActivityTask.from_poll(self.domain, self.task_list, polled_activity_data) task_token = activity_task.task_token return task_token, activity_task
def save(self): """Creates the workflow type amazon side""" try: self.connection.register_workflow_type( self.domain.name, self.name, self.version, task_list=str(self.task_list), default_child_policy=str(self.child_policy), default_execution_start_to_close_timeout=str(self.execution_timeout), default_task_start_to_close_timeout=str(self.decision_tasks_timeout), description=self.description ) except SWFTypeAlreadyExistsError: raise AlreadyExistsError("Workflow type %s already exists amazon-side" % self.name) except SWFResponseError as e: if e.error_code == 'UnknownResourceFault': raise DoesNotExistError(e.body['message'])
def _diff(self): """Checks for differences between WorkflowExecution instance and upstream version :returns: A swf.models.base.ModelDiff describing differences :rtype: ModelDiff """ try: description = self.connection.describe_workflow_execution( self.domain.name, self.run_id, self.workflow_id) except SWFResponseError as e: if e.error_code == "UnknownResourceFault": raise DoesNotExistError("Remote Domain does not exist") raise ResponseError(e.body["message"]) execution_info = description["executionInfo"] execution_config = description["executionConfiguration"] return ModelDiff( ( "workflow_id", self.workflow_id, execution_info["execution"]["workflowId"], ), ("run_id", self.run_id, execution_info["execution"]["runId"]), ("status", self.status, execution_info["executionStatus"]), ("task_list", self.task_list, execution_config["taskList"]["name"]), ("child_policy", self.child_policy, execution_config["childPolicy"]), ( "execution_timeout", self.execution_timeout, execution_config["executionStartToCloseTimeout"], ), ("tag_list", self.tag_list, execution_info.get("tagList")), ( "decision_tasks_timeout", self.decision_tasks_timeout, execution_config["taskStartToCloseTimeout"], ), )
def get(self, name, *args, **kwargs): """Fetches the Domain with `name` :param name: name of the domain to fetch :type name: string A typical Amazon response looks like: .. code-block:: json { "configuration": { "workflowExecutionRetentionPeriodInDays": "7", }, "domainInfo": { "status": "REGISTERED", "name": "CrawlTest", } } """ try: response = self.connection.describe_domain(name) except SWFResponseError as e: # If resource does not exist, amazon throws 400 with # UnknownResourceFault exception if e.error_code == "UnknownResourceFault": raise DoesNotExistError("No such domain: %s" % name) elif e.error_code == "UnrecognizedClientException": raise InvalidCredentialsError("Invalid aws credentials supplied") # Any other errors should raise raise ResponseError(e.body["message"]) domain_info = response["domainInfo"] domain_config = response["configuration"] return Domain( domain_info["name"], status=domain_info["status"], retention_period=domain_config["workflowExecutionRetentionPeriodInDays"], connection=self.connection, )
def heartbeat(self, task_token, details=None): """Records activity task heartbeat :param task_token: canceled activity task token :type task_token: string :param details: provided details about cancel :type details: string """ try: return self.connection.record_activity_task_heartbeat( task_token, details) except boto.exception.SWFResponseError as e: if e.error_code == 'UnknownResourceFault': raise DoesNotExistError( "Unable to send heartbeat with token={}".format( task_token), e.body['message'], ) raise ResponseError(e.body['message'])
def cancel(self, task_token, details=None): """Responds to ``swf`` that the activity task was canceled :param task_token: canceled activity task token :type task_token: string :param details: provided details about cancel :type details: string """ try: return self.connection.respond_activity_task_canceled( task_token, details) except boto.exception.SWFResponseError as e: if e.error_code == 'UnknownResourceFault': raise DoesNotExistError( "Unable to cancel activity task with token={}".format( task_token), e.body['message'], ) raise ResponseError(e.body['message'])
def complete(self, task_token, result=None): """Responds to ``swf`` that the activity task is completed :param task_token: completed activity task token :type task_token: string :param result: The result of the activity task. :type result: string """ try: return self.connection.respond_activity_task_completed( task_token, result) except boto.exception.SWFResponseError as e: if e.error_code == 'UnknownResourceFault': raise DoesNotExistError( "Unable to complete activity task with token={}".format( task_token), e.body['message'], ) raise ResponseError(e.body['message'])
def _diff(self): """Checks for differences between ActivityType instance and upstream version :returns: A list (swf.models.base.ModelDiff) namedtuple describing differences :rtype: ModelDiff """ try: description = self.connection.describe_activity_type( self.domain.name, self.name, self.version) except SWFResponseError as err: if err.error_code == 'UnknownResourceFault': raise DoesNotExistError("Remote ActivityType does not exist") raise ResponseError(err.body['message']) info = description['typeInfo'] config = description['configuration'] return ModelDiff( ('name', self.name, info['activityType']['name']), ('version', self.version, info['activityType']['version']), ('status', self.status, info['status']), ('description', self.description, info['description']), ('creation_date', self.creation_date, info['creationDate']), ('deprecation_date', self.deprecation_date, info['deprecationDate']), ('task_list', self.task_list, config['defaultTaskList']['name']), ('task_heartbeat_timeout', self.task_heartbeat_timeout, config['defaultTaskHeartbeatTimeout']), ('task_schedule_to_close_timeout', self.task_schedule_to_close_timeout, config['defaultTaskScheduleToCloseTimeout']), ('task_schedule_to_start_timeout', self.task_schedule_to_start_timeout, config['defaultTaskScheduleToStartTimeout']), ('task_start_to_close_timeout', self.task_start_to_close_timeout, config['defaultTaskStartToCloseTimeout']), )
def get(self, workflow_id, run_id, *args, **kwargs): """ """ try: response = self.connection.describe_workflow_execution( self.domain.name, run_id, workflow_id) except SWFResponseError as e: if e.error_code == 'UnknownResourceFault': raise DoesNotExistError(e.body['message']) raise ResponseError(e.body['message']) execution_info = response[self._infos] execution_config = response['executionConfiguration'] return self.to_WorkflowExecution( self.domain, execution_info, task_list=get_subkey(execution_config, ['defaultTaskList', 'name']), child_policy=execution_config.get('childPolicy'), execution_timeout=execution_config.get('executionStartToCloseTimeout'), decision_tasks_timeout=execution_config.get('taskStartToCloseTimeout'), )
class ActivityType(BaseModel): """ActivityType wrapper :param domain: Domain the workflow type should be registered in :type domain: swf.models.Domain :param name: name of the ActivityType :type name: str :param version: version of the ActivityType :type version: str :param status: ActivityType status :type status: swf.constants.{REGISTERED, DEPRECATED} :param description: ActivityType description :type description: str | None :param creation_date: creation date of the current ActivityType :type creation_date: float (timestamp) :param deprecation_date: deprecation date of ActivityType :type deprecation_date: float (timestamp) :param task_list: specifies the default task list to use for scheduling tasks of this activity type. :type task_list: str :param task_heartbeat_timeout: default maximum time before which a worker processing a task of this type must report progress by calling RecordActivityTaskHeartbeat. :type task_heartbeat_timeout: int :param task_schedule_to_close_timeout: default maximum duration for a task of this activity type. :type task_schedule_to_close_timeout: int :param task_schedule_to_start_timeout: default maximum duration that a task of this activity type can wait before being assigned to a worker. :type task_schedule_to_start_timeout: int :param task_start_to_close_timeout: default maximum duration that a worker can take to process tasks of this activity type. :type task_start_to_close_timeout: int """ kind = 'type' __slots__ = [ 'domain', 'name', 'version', 'status', 'description', 'creation_date', 'deprecation_date', 'task_list', 'task_heartbeat_timeout', 'task_schedule_to_close_timeout', 'task_schedule_to_start_timeout', 'task_start_to_close_timeout', ] def __init__(self, domain, name, version, status=REGISTERED, description=None, creation_date=0.0, deprecation_date=0.0, task_list=None, task_heartbeat_timeout=0, task_schedule_to_close_timeout=0, task_schedule_to_start_timeout=0, task_start_to_close_timeout=0, *args, **kwargs): self.domain = domain self.name = name self.version = version self.status = status self.description = description self.creation_date = creation_date self.deprecation_date = deprecation_date self.task_list = task_list self.task_heartbeat_timeout = task_heartbeat_timeout self.task_schedule_to_close_timeout = task_schedule_to_close_timeout self.task_schedule_to_start_timeout = task_schedule_to_start_timeout self.task_start_to_close_timeout = task_start_to_close_timeout # immutable decorator rebinds class name, # so have to use generice self.__class__ super(self.__class__, self).__init__(*args, **kwargs) def _diff(self): """Checks for differences between ActivityType instance and upstream version :returns: A list of swf.models.base.ModelDiff namedtuple describing differences :rtype: list """ try: description = self.connection.describe_activity_type( self.name, self.name, self.version ) except SWFResponseError as err: if err.error_code == 'UnknownResourceFault': raise DoesNotExistError("Remote ActivityType does not exist") raise ResponseError(err.body['message']) info = description['typeInfo'] config = description['configuration'] return ModelDiff( ('name', self.name, info['activityType']['name']), ('version', self.version, info['activityType']['version']), ('status', self.status, info['status']), ('description', self.description, info['description']), ('creation_date', self.creation_date, info['creationDate']), ('deprecation_date', self.deprecation_date, info['deprecationDate']), ('task_list', self.task_list, config['defaultTaskList']['name']), ('task_heartbeat_timeout', self.task_heartbeat_timeout, config['defaultTaskHeartbeatTimeout']), ('task_schedule_to_close_timeout', self.task_schedule_to_close_timeout, config['defaultTaskScheduleToCloseTimeout']), ('task_schedule_to_start_timeout', self.task_schedule_to_start_timeout, config['defaultTaskScheduleToStartTimeout']), ('task_start_to_close_timeout', self.task_start_to_close_timeout, config['defaultTaskStartToCloseTimeout']), ) @property @exceptions.is_not(ActivityTypeDoesNotExist) @exceptions.when(SWFResponseError, raises(ActivityTypeDoesNotExist, when=exceptions.is_unknown('ActivityType'), extract=exceptions.extract_resource)) def exists(self): """Checks if the ActivityType exists amazon-side :rtype: bool """ self.connection.describe_activity_type( self.domain.name, self.name, self.version ) return True def save(self): """Creates the activity type amazon side""" try: self.connection.register_activity_type( self.domain.name, self.name, self.version, task_list=str(self.task_list), default_task_heartbeat_timeout=str(self.task_heartbeat_timeout), default_task_schedule_to_close_timeout=str(self.task_schedule_to_close_timeout), default_task_schedule_to_start_timeout=str(self.task_schedule_to_start_timeout), default_task_start_to_close_timeout=str(self.task_start_to_close_timeout), description=self.description) except SWFTypeAlreadyExistsError, err: raise AlreadyExistsError('{} already exists'.format(self)) except SWFResponseError as err: if err.error_code in ['UnknownResourceFault', 'TypeDeprecatedFault']: raise DoesNotExistError(err.body['message']) raise
def poll(self, task_list=None, identity=None, **kwargs): """ Polls a decision task and returns the token and the full history of the workflow's events. :param task_list: task list to poll for decision tasks from. :type task_list: str :param identity: Identity of the decider making the request, which is recorded in the DecisionTaskStarted event in the workflow history. :type identity: str :returns: a Response object with history, token, and execution set :rtype: swf.responses.Response """ task_list = task_list or self.task_list task = self.connection.poll_for_decision_task(self.domain.name, task_list=task_list, identity=identity, **kwargs) token = task.get('taskToken') if token is None: raise PollTimeout("Decider poll timed out") events = task['events'] next_page = task.get('nextPageToken') while next_page: try: task = self.connection.poll_for_decision_task( self.domain.name, task_list=task_list, identity=identity, next_page_token=next_page, **kwargs) except boto.exception.SWFResponseError as e: if e.error_code == 'UnknownResourceFault': raise DoesNotExistError( "Unable to poll decision task", e.body['message'], ) raise ResponseError(e.body['message']) token = task.get('taskToken') if token is None: raise PollTimeout("Decider poll timed out") events.extend(task['events']) next_page = task.get('nextPageToken') history = History.from_event_list(events) workflow_type = WorkflowType( domain=self.domain, name=task['workflowType']['name'], version=task['workflowType']['version'], ) execution = WorkflowExecution( domain=self.domain, workflow_id=task['workflowExecution']['workflowId'], run_id=task['workflowExecution']['runId'], workflow_type=workflow_type, ) # TODO: move history into execution (needs refactoring on WorkflowExecution.history()) return Response(token=token, history=history, execution=execution)
def get(self, name, version, *args, **kwargs): """Fetches the Workflow Type with `name` and `version` :param name: name of the workflow type :type name: String :param version: workflow type version :type version: String :returns: matched workflow type instance :rtype: swf.core.model.workflow.WorkflowType A typical Amazon response looks like: .. code-block:: json { "configuration": { "defaultExecutionStartToCloseTimeout": "300", "defaultTaskStartToCloseTimeout": "300", "defaultTaskList": { "name": "None" }, "defaultChildPolicy": "TERMINATE" }, "typeInfo": { "status": "REGISTERED", "creationDate": 1364492094.968, "workflowType": { "version": "1", "name": "testW" } } } """ try: response = self.connection.describe_workflow_type( self.domain.name, name, version ) except SWFResponseError as e: if e.error_code == "UnknownResourceFault": raise DoesNotExistError(e.body["message"]) raise ResponseError(e.body["message"]) wt_info = response[self._infos] wt_config = response["configuration"] task_list = kwargs.get("task_list") if task_list is None: task_list = get_subkey(wt_config, ["defaultTaskList", "name"]) child_policy = kwargs.get("child_policy") if child_policy is None: child_policy = wt_config.get("defaultChildPolicy") decision_task_timeout = kwargs.get("decision_task_timeout") if decision_task_timeout is None: decision_task_timeout = wt_config.get("defaultTaskStartToCloseTimeout") execution_timeout = kwargs.get("execution_timeout") if execution_timeout is None: execution_timeout = wt_config.get("defaultExecutionStartToCloseTimeout") decision_tasks_timeout = kwargs.get("decision_tasks_timeout") if decision_tasks_timeout is None: decision_tasks_timeout = wt_config.get("defaultTaskStartToCloseTimeout") return self.to_WorkflowType( self.domain, wt_info, task_list=task_list, child_policy=child_policy, execution_timeout=execution_timeout, decision_tasks_timeout=decision_tasks_timeout, )