class InvocationBuilder(object): """builder for the ToFunction message""" def __init__(self): self.to_function = ToFunction() def with_target(self, ns, type, id): InvocationBuilder.set_address(ns, type, id, self.to_function.invocation.target) return self def with_state(self, name, value=None): state = self.to_function.invocation.state.add() state.state_name = name if value: any = Any() any.Pack(value) state.state_value = any.SerializeToString() return self def with_invocation(self, arg, caller=None): invocation = self.to_function.invocation.invocations.add() if caller: (ns, type, id) = caller InvocationBuilder.set_address(ns, type, id, invocation.caller) invocation.argument.Pack(arg) return self def SerializeToString(self): return self.to_function.SerializeToString() @staticmethod def set_address(namespace, type, id, address): address.namespace = namespace address.type = type address.id = id
def _run_flink_loop(self, message_arg: Union[TaskRequest, TaskResult, TaskException, TaskActionRequest], target: Address, caller=None): to_function = ToFunction() update_address(to_function.invocation.target, target.namespace, target.type, target.id) invocation = to_function.invocation.invocations.add() if caller: update_address(invocation.caller, caller.namespace, caller.type, caller.id) invocation.argument.Pack(message_arg) self._copy_state_to_invocation(target.namespace, target.type, target.id, to_function) result_bytes = asyncio.get_event_loop().run_until_complete( async_handler(to_function.SerializeToString())) result = self._process_result(to_function, result_bytes) if result.egress_message is not None: return result.egress_message else: outgoing_messages = result.outgoing_messages for outgoing_message in outgoing_messages: message_arg = unpack_any( outgoing_message.argument, [TaskRequest, TaskResult, TaskException]) egress_value = self._run_flink_loop( message_arg=message_arg, target=outgoing_message.target, caller=target) if egress_value: return egress_value
class InvocationBuilder(object): """builder for the ToFunction message""" def __init__(self): self.to_function = ToFunction() def with_target(self, ns, type, id): InvocationBuilder.set_address(ns, type, id, self.to_function.invocation.target) return self def with_state(self, name, value=None): state = self.to_function.invocation.state.add() state.state_name = name if value: state.state_value.CopyFrom(self.to_typed_value_any_state(value)) return self def with_invocation(self, arg, caller=None): invocation = self.to_function.invocation.invocations.add() if caller: (ns, type, id) = caller InvocationBuilder.set_address(ns, type, id, invocation.caller) invocation.argument.CopyFrom(self.to_typed_value(arg)) return self def SerializeToString(self): return self.to_function.SerializeToString() @staticmethod def to_typed_value(proto_msg): any = Any() any.Pack(proto_msg) typed_value = TypedValue() typed_value.typename = any.type_url typed_value.value = any.value return typed_value @staticmethod def to_typed_value_any_state(proto_msg): any = Any() any.Pack(proto_msg) typed_value = TypedValue() typed_value.typename = "type.googleapis.com/google.protobuf.Any" typed_value.value = any.SerializeToString() return typed_value @staticmethod def set_address(namespace, type, id, address): address.namespace = namespace address.type = type address.id = id
def _run_flink_loop(self, message_arg, target: Address, caller=None, egress_result=None): to_function = ToFunction() update_address(to_function.invocation.target, target.namespace, target.type, target.id) invocation = to_function.invocation.invocations.add() if caller: update_address(invocation.caller, caller.namespace, caller.type, caller.id) if isinstance(message_arg, TypedValue): # function calling function invocation.argument.CopyFrom(message_arg) else: flink_type = flink_value_type_for( message_arg ) # ingress protobuf needs to to be wrapped into a TypedValue invocation.argument.CopyFrom( TypedValue(typename=flink_type.typename, has_value=True, value=message_arg.SerializeToString())) self._copy_state_to_invocation(target.namespace, target.type, target.id, to_function) result_bytes = asyncio.get_event_loop().run_until_complete( handler.handle_async(to_function.SerializeToString())) result = self._process_result(to_function, result_bytes) # remember first egress result if result.egress_message is not None and egress_result is None: egress_result = result.egress_message # recurse while we have outgoing messages outgoing_messages = result.outgoing_messages for outgoing_message in outgoing_messages: egress_value = self._run_flink_loop( message_arg=outgoing_message.argument, target=outgoing_message.target, caller=target, egress_result=egress_result) if egress_value: return egress_value return egress_result