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 """ logging_context.reset() task_list = task_list or self.task_list task = self.connection.poll_for_decision_task( self.domain.name, task_list=task_list, identity=format.identity(identity), **kwargs) token = task.get('taskToken') if token is None: raise PollTimeout("Decider poll timed out") events = task['events'] logging_context.set("workflow_id", task["workflowExecution"]["workflowId"]) logging_context.set("task_type", "decision") logging_context.set("event_id", task["startedEventId"]) next_page = task.get('nextPageToken') while next_page: try: task = self.connection.poll_for_decision_task( self.domain.name, task_list=task_list, identity=format.identity(identity), next_page_token=next_page, **kwargs) except boto.exception.SWFResponseError as e: message = self.get_error_message(e) if e.error_code == 'UnknownResourceFault': raise DoesNotExistError( "Unable to poll decision task", message, ) raise ResponseError(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, )
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: string :param identity: Identity of the decider making the request, which is recorded in the DecisionTaskStarted event in the workflow history. :type identity: string :returns: (token, history) :type: swf.models.History """ 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.\n", 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) return token, history
def get(self, name, version, *args, **kwargs): """Fetches the activity type with provided ``name`` and ``version`` :param name: activity type name to fetch :type name: String :param version: activity version to fetch :type version: String :returns: Matched activity type instance :rtype: swf.models.activity.ActivityType A typical Amazon response looks like: .. code-block:: json { "configuration": { "defaultTaskHeartbeatTimeout": "string", "defaultTaskList": { "name": "string" }, "defaultTaskScheduleToCloseTimeout": "string", "defaultTaskScheduleToStartTimeout": "string", "defaultTaskStartToCloseTimeout": "string" }, "typeInfo": { "activityType": { "name": "string", "version": "string" }, "creationDate": "number", "deprecationDate": "number", "description": "string", "status": "string" } } """ try: response = self.connection.describe_activity_type( self.domain.name, name, version ) except SWFResponseError as e: if e.error_code == "UnknownResourceFault": raise DoesNotExistError(e.error_message) raise ResponseError(e.error_message) activity_info = response[self._infos] activity_config = response["configuration"] task_list = kwargs.get("task_list") if task_list is None: task_list = get_subkey(activity_config, ["defaultTaskList", "name"]) task_heartbeat_timeout = kwargs.get("task_heartbeat_timeout") if task_heartbeat_timeout is None: task_heartbeat_timeout = activity_config.get("defaultTaskHeartbeatTimeout") task_schedule_to_close_timeout = kwargs.get("task_schedule_to_close_timeout") if task_schedule_to_close_timeout is None: task_schedule_to_close_timeout = activity_config.get( "defaultTaskScheduleToCloseTimeout" ) task_schedule_to_start_timeout = kwargs.get("task_schedule_to_start_timeout") if task_schedule_to_start_timeout is None: task_schedule_to_start_timeout = activity_config.get( "defaultTaskScheduleToStartTimeout" ) task_start_to_close_timeout = kwargs.get("task_start_to_close_timeout") if task_start_to_close_timeout is None: task_start_to_close_timeout = activity_config.get( "defaultTaskStartToCloseTimeout" ) return self.to_ActivityType( self.domain, activity_info, task_list=task_list, task_heartbeat_timeout=task_heartbeat_timeout, task_schedule_to_close_timeout=task_schedule_to_close_timeout, task_schedule_to_start_timeout=task_schedule_to_start_timeout, task_start_to_close_timeout=task_start_to_close_timeout, )
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 'taskToken' not in task: 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, )