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 complete(service, task_token, return_value: object) -> Optional[Exception]: respond = RespondActivityTaskCompletedRequest() respond.task_token = task_token respond.result = json.dumps(return_value) respond.identity = WorkflowService.get_identity() _, error = service.respond_activity_task_completed(respond) return error
def complete_exceptionally(service, task_token, ex: Exception) -> Optional[Exception]: respond: RespondActivityTaskFailedRequest = RespondActivityTaskFailedRequest() respond.task_token = task_token respond.identity = WorkflowService.get_identity() respond.reason = "ActivityFailureException" respond.details = serialize_exception(ex) _, error = service.respond_activity_task_failed(respond) return error
def heartbeat(service: WorkflowService, task_token: bytes, details: object): request = RecordActivityTaskHeartbeatRequest() request.details = json.dumps(details).encode("utf-8") request.identity = WorkflowService.get_identity() request.task_token = task_token response, error = service.record_activity_task_heartbeat(request) if error: raise error if response.cancel_requested: raise ActivityCancelledException()
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 respond_decisions(self, task_token: bytes, decisions: List[Decision]): service = self.service request = RespondDecisionTaskCompletedRequest() request.task_token = task_token request.decisions.extend(decisions) request.identity = WorkflowService.get_identity() # noinspection PyUnusedLocal response: RespondDecisionTaskCompletedResponse response, err = service.respond_decision_task_completed(request) if err: logger.error("Error invoking RespondDecisionTaskCompleted: %s", err) else: logger.debug("RespondDecisionTaskCompleted: %s", response)
def test_heartbeat(activity_context: ActivityContext): response = Mock() response.cancel_requested = False activity_context.service.record_activity_task_heartbeat = Mock( return_value=(response, None)) activity_context.heartbeat("payload") args, kwargs = activity_context.service.record_activity_task_heartbeat.call_args_list[ 0] assert isinstance(args[0], RecordActivityTaskHeartbeatRequest) request: RecordActivityTaskHeartbeatRequest = args[0] assert request.details == json.dumps("payload").encode("utf-8") assert request.task_token == "task-token" assert request.identity == WorkflowService.get_identity()
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