async def schedule_activity_task(self, parameters: ExecuteActivityParameters): attr = ScheduleActivityTaskDecisionAttributes() attr.activity_type = parameters.activity_type attr.input = parameters.input if parameters.heartbeat_timeout_seconds > 0: attr.heartbeat_timeout_seconds = parameters.heartbeat_timeout_seconds attr.schedule_to_close_timeout_seconds = parameters.schedule_to_close_timeout_seconds attr.schedule_to_start_timeout_seconds = parameters.schedule_to_start_timeout_seconds attr.start_to_close_timeout_seconds = parameters.start_to_close_timeout_seconds attr.activity_id = parameters.activity_id if not attr.activity_id: attr.activity_id = self.decider.get_and_increment_next_id() attr.task_list = TaskList() attr.task_list.name = parameters.task_list # PORT: RetryParameters retryParameters = parameters.getRetryParameters(); # PORT: if (retryParameters != null) { # PORT: attributes.setRetryPolicy(retryParameters.toRetryPolicy()); # PORT: } scheduled_event_id = self.decider.schedule_activity_task(schedule=attr) future = self.decider.event_loop.create_future() self.scheduled_activities[scheduled_event_id] = future await future assert future.done() exception = future.exception() if exception: raise exception raw_bytes = future.result() return json.loads(str(raw_bytes, "utf-8"))
def poll(self) -> Optional[PollForDecisionTaskResponse]: try: polling_start = datetime.datetime.now() poll_decision_request = PollForDecisionTaskRequest() poll_decision_request.identity = WorkflowService.get_identity() poll_decision_request.task_list = TaskList() poll_decision_request.task_list.name = self.worker.task_list poll_decision_request.domain = self.worker.domain # noinspection PyUnusedLocal task: PollForDecisionTaskResponse task, err = self.service.poll_for_decision_task( poll_decision_request) polling_end = datetime.datetime.now() logger.debug("PollForDecisionTask: %dms", (polling_end - polling_start).total_seconds() * 1000) except TChannelException as ex: logger.error("PollForDecisionTask error: %s", ex) return None if err: logger.error("PollForDecisionTask failed: %s", err) return None if not task.task_token: logger.debug( "PollForActivityTask has no task token (expected): %s", task) return None return task
def test_poll_for_activity_task_timeout(self): request = PollForActivityTaskRequest() request.domain = "test-domain" request.identity = WorkflowService.get_identity() request.task_list = TaskList() request.task_list.name = "test-task-list" response, err = self.service.poll_for_activity_task(request) self.assertIsNone(err) self.assertIsNotNone(response) self.assertIsNone(response.task_token)
def test_poll_for_decision_task(self): request = PollForDecisionTaskRequest() request.identity = "123@localhost" request.domain = "test-domain" request.task_list = TaskList() request.task_list.name = "test-task-list" + str(uuid4()) response, err = self.service.poll_for_decision_task(request) self.assertIsNone(err) self.assertIsNotNone(response) self.assertIsNone(response.task_token)
def test_describe_task_list(self): request = DescribeTaskListRequest() request.task_list = TaskList() request.task_list.name = "test-task-list" request.task_list_type = TaskListType.Decision request.domain = "test-domain" response, err = self.service.describe_task_list(request) self.assertIsNone(err) self.assertIsNotNone(response) self.assertIsInstance(response, DescribeTaskListResponse) self.assertEqual(0, len(response.pollers))
def setUp(self) -> None: self.service = WorkflowService.create("localhost", 7933) self.request = request = StartWorkflowExecutionRequest() request.domain = "test-domain" request.request_id = str(uuid4()) request.task_list = TaskList() request.task_list.name = "test-task-list" request.input = "abc-firdaus" request.workflow_id = str(uuid4()) request.workflow_type = WorkflowType() request.workflow_type.name = "firdaus-workflow-type" request.execution_start_to_close_timeout_seconds = 86400 request.task_start_to_close_timeout_seconds = 120 time.sleep(0.5)
def test_signal_with_start_workflow_execution(self): request = SignalWithStartWorkflowExecutionRequest() request.signal_name = "dummy-signal" request.domain = "test-domain" request.request_id = str(uuid4()) request.task_list = TaskList() request.task_list.name = "test-task-list" request.input = "abc-firdaus" request.workflow_id = str(uuid4()) request.workflow_type = WorkflowType() request.workflow_type.name = "firdaus-workflow-type" request.execution_start_to_close_timeout_seconds = 86400 request.task_start_to_close_timeout_seconds = 120 response, err = self.service.signal_with_start_workflow_execution(request) self.assertIsNone(err) self.assertIsNotNone(response) self.assertIsInstance(response, StartWorkflowExecutionResponse)
def create_start_workflow_request(workflow_client: WorkflowClient, wm: WorkflowMethod, args: List) -> StartWorkflowExecutionRequest: start_request = StartWorkflowExecutionRequest() start_request.domain = workflow_client.domain start_request.workflow_id = wm._workflow_id if wm._workflow_id else str(uuid4()) start_request.workflow_type = WorkflowType() start_request.workflow_type.name = wm._name start_request.task_list = TaskList() start_request.task_list.name = wm._task_list start_request.input = args_to_json(args) start_request.execution_start_to_close_timeout_seconds = wm._execution_start_to_close_timeout_seconds start_request.task_start_to_close_timeout_seconds = wm._task_start_to_close_timeout_seconds start_request.identity = workflow_client.service.get_identity() start_request.workflow_id_reuse_policy = wm._workflow_id_reuse_policy start_request.request_id = str(uuid4()) start_request.cron_schedule = wm._cron_schedule if wm._cron_schedule else None return start_request
async def schedule_activity_task(self, parameters: ExecuteActivityParameters): attr = ScheduleActivityTaskDecisionAttributes() attr.activity_type = parameters.activity_type attr.input = parameters.input if parameters.heartbeat_timeout_seconds > 0: attr.heartbeat_timeout_seconds = parameters.heartbeat_timeout_seconds attr.schedule_to_close_timeout_seconds = parameters.schedule_to_close_timeout_seconds attr.schedule_to_start_timeout_seconds = parameters.schedule_to_start_timeout_seconds attr.start_to_close_timeout_seconds = parameters.start_to_close_timeout_seconds attr.activity_id = parameters.activity_id if not attr.activity_id: attr.activity_id = self.decider.get_and_increment_next_id() attr.task_list = TaskList() attr.task_list.name = parameters.task_list if parameters.retry_parameters: attr.retry_policy = parameters.retry_parameters.to_retry_policy() scheduled_event_id = self.decider.schedule_activity_task(schedule=attr) future = self.decider.event_loop.create_future() self.scheduled_activities[scheduled_event_id] = future try: await future except CancelledError as e: logger.debug("Coroutine cancelled (expected)") raise e except Exception as ex: pass ex = future.exception() if ex: activity_failure = ActivityFailureException( scheduled_event_id, parameters.activity_type.name, parameters.activity_id, serialize_exception(ex)) raise activity_failure assert future.done() raw_bytes = future.result() return json.loads(str(raw_bytes, "utf-8"))
def activity_task_loop(worker: Worker): service: WorkflowService = WorkflowService.create( worker.host, worker.port, timeout=worker.get_timeout()) worker.manage_service(service) logger.info( f"Activity task worker started: {WorkflowService.get_identity()}") try: while True: if worker.is_stop_requested(): return try: service.set_next_timeout_cb(worker.raise_if_stop_requested) polling_start = datetime.datetime.now() polling_request = PollForActivityTaskRequest() polling_request.task_list_metadata = TaskListMetadata() polling_request.task_list_metadata.max_tasks_per_second = 200000 polling_request.domain = worker.domain polling_request.identity = WorkflowService.get_identity() polling_request.task_list = TaskList() polling_request.task_list.name = worker.task_list task: PollForActivityTaskResponse task, err = service.poll_for_activity_task(polling_request) polling_end = datetime.datetime.now() logger.debug("PollForActivityTask: %dms", (polling_end - polling_start).total_seconds() * 1000) except StopRequestedException: return except Exception as ex: logger.error("PollForActivityTask error: %s", ex) continue if err: logger.error("PollForActivityTask failed: %s", err) continue task_token = task.task_token if not task_token: logger.debug( "PollForActivityTask has no task_token (expected): %s", task) continue args = json_to_args(task.input) logger.info(f"Request for activity: {task.activity_type.name}") fn = worker.activities.get(task.activity_type.name) if not fn: logger.error("Activity type not found: " + task.activity_type.name) continue process_start = datetime.datetime.now() activity_context = ActivityContext() activity_context.service = service activity_context.activity_task = ActivityTask.from_poll_for_activity_task_response( task) activity_context.domain = worker.domain try: ActivityContext.set(activity_context) return_value = fn(*args) if activity_context.do_not_complete: logger.info( f"Not completing activity {task.activity_type.name}({str(args)[1:-1]})" ) continue error = complete(service, task_token, return_value) if error: logger.error( "Error invoking RespondActivityTaskCompleted: %s", error) logger.info( f"Activity {task.activity_type.name}({str(args)[1:-1]}) returned {json.dumps(return_value)}" ) except Exception as ex: logger.error( f"Activity {task.activity_type.name} failed: {type(ex).__name__}({ex})", exc_info=1) error = complete_exceptionally(service, task_token, ex) if error: logger.error( "Error invoking RespondActivityTaskFailed: %s", error) finally: ActivityContext.set(None) process_end = datetime.datetime.now() logger.info("Process ActivityTask: %dms", (process_end - process_start).total_seconds() * 1000) finally: try: service.close() except: logger.warning("service.close() failed", exc_info=1) worker.notify_thread_stopped()
def activity_task_loop(worker): service = WorkflowService.create(worker.host, worker.port) logger.info( f"Activity task worker started: {WorkflowService.get_identity()}") try: while True: if worker.is_stop_requested(): return try: polling_start = datetime.datetime.now() polling_request = PollForActivityTaskRequest() polling_request.task_list_metadata = TaskListMetadata() polling_request.task_list_metadata.max_tasks_per_second = 200000 polling_request.domain = worker.domain polling_request.identity = WorkflowService.get_identity() polling_request.task_list = TaskList() polling_request.task_list.name = worker.task_list task: PollForActivityTaskResponse task, err = service.poll_for_activity_task(polling_request) polling_end = datetime.datetime.now() logger.debug("PollForActivityTask: %dms", (polling_end - polling_start).total_seconds() * 1000) except Exception as ex: logger.error("PollForActivityTask error: %s", ex) continue if err: logger.error("PollForActivityTask failed: %s", err) continue if not task.task_token: logger.debug( "PollForActivityTask has no task_token (expected): %s", task) continue args = json.loads(task.input) logger.info(f"Request for activity: {task.activity_type.name}") fn = worker.activities.get(task.activity_type.name) if not fn: logger.error("Activity type not found: " + task.activity_type.name) continue process_start = datetime.datetime.now() try: ret = fn(*args) respond = RespondActivityTaskCompletedRequest() respond.task_token = task.task_token respond.result = json.dumps(ret) respond.identity = WorkflowService.get_identity() _, error = service.respond_activity_task_completed(respond) if error: logger.error( "Error invoking RespondActivityTaskCompleted: %s", error) logger.info( f"Activity {task.activity_type.name}({str(args)[1:-1]}) returned {respond.result}" ) except Exception as ex: logger.error( f"Activity {task.activity_type.name} failed: {type(ex).__name__}({ex})", exc_info=1) respond: RespondActivityTaskFailedRequest = RespondActivityTaskFailedRequest( ) respond.task_token = task.task_token respond.identity = WorkflowService.get_identity() respond.details = json.dumps({ "detailMessage": f"Python error: {type(ex).__name__}({ex})", "class": "java.lang.Exception" }) respond.reason = "java.lang.Exception" _, error = service.respond_activity_task_failed(respond) if error: logger.error( "Error invoking RespondActivityTaskFailed: %s", error) process_end = datetime.datetime.now() logger.info("Process ActivityTask: %dms", (process_end - process_start).total_seconds() * 1000) finally: worker.notify_thread_stopped()
import json from cadence.cadence_types import PollForActivityTaskResponse, RespondActivityTaskCompletedRequest, PollForActivityTaskRequest, \ TaskList from cadence.workflowservice import WorkflowService service = WorkflowService.create("localhost", 7933) while True: task: PollForActivityTaskResponse try: polling_request = PollForActivityTaskRequest() polling_request.domain = "sample" polling_request.identity = WorkflowService.get_identity() polling_request.task_list = TaskList() polling_request.task_list.name = "python-tasklist" task, error = service.poll_for_activity_task(polling_request) except Exception as ex: # Most probably a Timeout continue if error: print("Error: " + error) continue print("Request: " + str(task)) input = json.loads(task.input) greeting = input[0] name = input[1] output = json.dumps(greeting + " " + name + "!") print(task.task_token) respond_activity_completed_request = RespondActivityTaskCompletedRequest() respond_activity_completed_request.task_token = task.task_token
import dataclasses import json from cadence.cadence_types import GetWorkflowExecutionHistoryRequest, WorkflowExecution, PollForDecisionTaskRequest, \ TaskList from cadence.workflowservice import WorkflowService class Encoder(json.JSONEncoder): def default(self, o): if dataclasses.is_dataclass(o): return dataclasses.asdict(o) if isinstance(o, bytes): return str(o, 'utf-8') return super().default(o) if __name__ == "__main__": service = WorkflowService.create("localhost", 7933) while True: poll_request = PollForDecisionTaskRequest() poll_request.domain = "sample" poll_request.identity = service.get_identity() poll_request.task_list = TaskList() poll_request.task_list.name = "python-tasklist" poll_response, err = service.poll_for_decision_task(poll_request) print(json.dumps(poll_response, cls=Encoder, indent=2))