async def complete_exceptionally(service, task_token, ex: Exception): respond: RespondActivityTaskFailedRequest = RespondActivityTaskFailedRequest( ) respond.task_token = task_token respond.identity = get_identity() respond.failure = serialize_exception(ex) await service.respond_activity_task_failed(request=respond)
async def complete(client: "WorkflowClient", task_token, return_value: object): respond = RespondActivityTaskCompletedRequest() respond.task_token = task_token respond.namespace = client.namespace respond.identity = get_identity() respond.result = client.data_converter.to_payloads([return_value]) await client.service.respond_activity_task_completed(request=respond)
async def complete_exceptionally(client: "WorkflowClient", task_token, ex: Exception): respond: RespondActivityTaskFailedRequest = RespondActivityTaskFailedRequest( ) respond.task_token = task_token respond.namespace = client.namespace respond.identity = get_identity() respond.failure = serialize_exception(ex) await client.service.respond_activity_task_failed(request=respond)
async def heartbeat(service: WorkflowService, task_token: bytes, details: object): request: RecordActivityTaskHeartbeatRequest = RecordActivityTaskHeartbeatRequest( ) request.details = to_payloads([details]) request.identity = get_identity() request.task_token = task_token response = await service.record_activity_task_heartbeat(request=request) # ----- # if error: # raise error # ----- if response.cancel_requested: raise ActivityCancelledException()
async def heartbeat(client: "WorkflowClient", task_token: bytes, details: object): request: RecordActivityTaskHeartbeatRequest = RecordActivityTaskHeartbeatRequest( ) request.details = client.data_converter.to_payloads([details]) request.namespace = client.namespace request.identity = get_identity() request.task_token = task_token response = await client.service.record_activity_task_heartbeat( request=request) # ----- # if error: # raise error # ----- if response.cancel_requested: raise ActivityCancelledException()
async def test(worker): client = WorkflowClient.new_client(namespace=NAMESPACE) greeting_workflow: GreetingWorkflow = client.new_workflow_stub(GreetingWorkflow) context: WorkflowExecutionContext = await client.start( greeting_workflow.get_greeting ) await asyncio.sleep(60 * 3) assert invoke_count >= 2 request = TerminateWorkflowExecutionRequest() request.namespace = NAMESPACE request.identity = get_identity() request.workflow_execution = context.workflow_execution request.workflow_execution.run_id = None response: TerminateWorkflowExecutionResponse = ( await client.service.terminate_workflow_execution(request=request) )
async def activity_task_loop_func(worker: Worker): service: WorkflowService = worker.client.service logger.info(f"Activity task worker started: {get_identity()}") try: while True: if worker.is_stop_requested(): return try: polling_start = datetime.datetime.now() polling_request: PollActivityTaskQueueRequest = PollActivityTaskQueueRequest( ) polling_request.task_queue_metadata = TaskQueueMetadata() polling_request.task_queue_metadata.max_tasks_per_second = 200000 polling_request.namespace = worker.namespace polling_request.identity = get_identity() polling_request.task_queue = TaskQueue() polling_request.task_queue.name = worker.task_queue task: PollActivityTaskQueueResponse task = await service.poll_activity_task_queue( request=polling_request) polling_end = datetime.datetime.now() logger.debug("PollActivityTaskQueue: %dms", (polling_end - polling_start).total_seconds() * 1000) except StopRequestedException: return except GRPCError as ex: logger.error("Error invoking poll_activity_task_queue: %s", ex, exc_info=True) continue task_token = task.task_token if not task_token: logger.debug( "PollActivityTaskQueue has no task_token (expected): %s", task) continue 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 args: List[object] = worker.client.data_converter.from_payloads( task.input, get_fn_args_type_hints(fn)) process_start = datetime.datetime.now() activity_context = ActivityContext() activity_context.client = worker.client activity_context.activity_task = ActivityTask.from_poll_for_activity_task_response( task) activity_context.namespace = worker.namespace try: ActivityContext.set(activity_context) if inspect.iscoroutinefunction(fn): return_value = await fn(*args) else: raise Exception( f"Activity method {fn.__module__}.{fn.__qualname__} should be a coroutine" ) if activity_context.do_not_complete: logger.info( f"Not completing activity {task.activity_type.name}({str(args)[1:-1]})" ) continue logger.info( f"Activity {task.activity_type.name}({str(args)[1:-1]}) returned {return_value}" ) try: await complete(worker.client, task_token, return_value) except GRPCError as ex: logger.error( "Error invoking respond_activity_task_completed: %s", ex, exc_info=True) except Exception as ex: logger.error( f"Activity {task.activity_type.name} failed: {type(ex).__name__}({ex})", exc_info=True) try: await complete_exceptionally(worker.client, task_token, ex) except GRPCError as ex2: logger.error( "Error invoking respond_activity_task_failed: %s", ex2, exc_info=True) finally: ActivityContext.set(None) process_end = datetime.datetime.now() logger.info("Process ActivityTask: %dms", (process_end - process_start).total_seconds() * 1000) finally: worker.notify_thread_stopped() logger.info("Activity loop ended")
async def activity_task_loop_func(worker: Worker): service: WorkflowService = create_workflow_service(worker.host, worker.port, timeout=worker.get_timeout()) worker.manage_service(service) logger.info(f"Activity task worker started: {get_identity()}") try: while True: if worker.is_stop_requested(): return try: polling_start = datetime.datetime.now() polling_request: PollActivityTaskQueueRequest = PollActivityTaskQueueRequest() polling_request.task_queue_metadata = TaskQueueMetadata() polling_request.task_queue_metadata.max_tasks_per_second = 200000 polling_request.namespace = worker.namespace polling_request.identity = get_identity() polling_request.task_queue = TaskQueue() polling_request.task_queue.name = worker.task_queue task: PollActivityTaskQueueResponse task = await service.poll_activity_task_queue(request=polling_request) polling_end = datetime.datetime.now() logger.debug("PollActivityTaskQueue: %dms", (polling_end - polling_start).total_seconds() * 1000) except StopRequestedException: return except GRPCError as ex: logger.error("Error invoking poll_activity_task_queue: %s", ex, exc_info=True) continue task_token = task.task_token if not task_token: logger.debug("PollActivityTaskQueue has no task_token (expected): %s", task) continue args: List[object] = from_payloads(task.input) print(args) 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.namespace = worker.namespace try: ActivityContext.set(activity_context) if inspect.iscoroutinefunction(fn): return_value = await fn(*args) else: 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 logger.info( f"Activity {task.activity_type.name}({str(args)[1:-1]}) returned {json.dumps(return_value)}") try: await complete(service, task_token, return_value) except GRPCError as ex: logger.error("Error invoking respond_activity_task_completed: %s", ex, exc_info=True) except Exception as ex: logger.error(f"Activity {task.activity_type.name} failed: {type(ex).__name__}({ex})", exc_info=True) try: await complete_exceptionally(service, task_token, ex) except GRPCError as ex2: logger.error("Error invoking respond_activity_task_failed: %s", ex2, exc_info=True) finally: ActivityContext.set(None) process_end = datetime.datetime.now() logger.info("Process ActivityTask: %dms", (process_end - process_start).total_seconds() * 1000) finally: # noinspection PyBroadException try: service.channel.close() except Exception: logger.warning("service.close() failed", exc_info=True) worker.notify_thread_stopped() logger.info("Activity loop ended")
async def complete(service, task_token, return_value: object): respond = RespondActivityTaskCompletedRequest() respond.task_token = task_token respond.result = to_payloads([return_value]) respond.identity = get_identity() await service.respond_activity_task_completed(request=respond)