def handleStreamedIn(self, request_iterator, context): peek = request_iterator.next() # evidently, the first message has no payload # and is probably intended to prime the stream handler. logging.debug(f"peeked: {peek}") if peek.service_name in self.action_protocol_entities: handler = ActionHandler(self.action_protocol_entities[peek.service_name]) logging.debug(f"set stream in handler to {peek.service_name}") else: context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") reconstructed = (get_payload(x) for x in request_iterator) ctx = ActionContext(peek.name) try: result = handler.handle_stream_in( reconstructed, ctx ) # the proto the user defined function returned. client_action = ctx.create_client_action(result, False) action_reply = ActionResponse() if not ctx.has_errors(): action_reply.side_effects.extend(ctx.effects) if client_action.HasField("reply"): action_reply.reply.CopyFrom(client_action.reply) elif client_action.HasField("forward"): action_reply.forward.CopyFrom(client_action.forward) else: action_reply.failure.CopyFrom(client_action.failure) return action_reply except Exception as ex: ctx.fail(str(ex)) logging.exception("Failed to execute command:" + str(ex))
def handleStreamedOut(self, request, context): if request.service_name in self.action_protocol_entities: handler = ActionHandler(self.action_protocol_entities[request.service_name]) else: context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") reconstructed = get_payload(request) ctx = ActionContext(request.name) try: for result in handler.handle_stream_out(reconstructed, ctx): client_action = ctx.create_client_action(result, False) action_reply = ActionResponse() if not ctx.has_errors(): action_reply.side_effects.extend(ctx.effects) if client_action.HasField("reply"): action_reply.reply.CopyFrom(client_action.reply) elif client_action.HasField("forward"): action_reply.forward.CopyFrom(client_action.forward) else: action_reply.failure.CopyFrom(client_action.failure) yield action_reply except Exception as ex: ctx.fail(str(ex)) logging.exception("Failed to execute command:" + str(ex))
def handleUnary(self, request: ActionCommand, context): logging.info(f"handling unary {request} {context}.") if request.service_name in self.action_protocol_entities: service = self.action_protocol_entities[request.service_name] handler = ActionHandler(service) ctx = ActionContext(request.name) result = None try: result = handler.handle_unary( get_payload(request), ctx ) # the proto the user defined function returned. except Exception as ex: ctx.fail(str(ex)) logging.exception("Failed to execute command:" + str(ex)) client_action: ClientAction = ctx.create_client_action(result, False) action_reply = ActionResponse() if not ctx.has_errors(): action_reply.side_effects.extend(ctx.effects) if client_action.HasField("reply"): action_reply.reply.CopyFrom(client_action.reply) elif client_action.HasField("forward"): action_reply.forward.CopyFrom(client_action.forward) else: action_reply.failure.CopyFrom(client_action.failure) return action_reply
def handle(self, request_iterator, context): initiated = False current_state = None handler: EventSourcedHandler = None entity_id: str = None start_sequence_number: int = 0 for request in request_iterator: if not initiated: if request.HasField("init"): init: EventSourcedInit = request.init service_name = init.service_name entity_id = init.entity_id if service_name not in self.event_sourced_entities: raise Exception( "No event sourced entity registered for service {}".format( service_name ) ) entity = self.event_sourced_entities[service_name] handler = EventSourcedHandler(entity) current_state = handler.init_state(entity_id) initiated = True if init.HasField("snapshot"): event_sourced_snapshot: EventSourcedSnapshot = init.snapshot start_sequence_number = event_sourced_snapshot.snapshot_sequence snapshot = get_payload(event_sourced_snapshot.snapshot) snapshot_context = SnapshotContext( entity_id, start_sequence_number ) snapshot_result = handler.handle_snapshot( current_state, snapshot, snapshot_context ) if snapshot_result: current_state = snapshot_result else: raise Exception( "Cannot handle {} before initialization".format(request) ) elif request.HasField("event"): event: EventSourcedEvent = request.event evt = get_payload(event) event_result = handler.handle_event( current_state, evt, EventContext(entity_id, event.sequence) ) start_sequence_number = event.sequence if event_result: current_state = event_result pprint("Handling event {}".format(event)) elif request.HasField("command"): command: Command = request.command cmd = get_payload(command) ctx = EventSourcedCommandContext( command.name, command.id, entity_id, start_sequence_number ) result = None try: result = handler.handle_command(current_state, cmd, ctx) except Exception as ex: ctx.fail(str(ex)) logging.exception("Failed to execute command:" + str(ex)) client_action = ctx.create_client_action(result, False) event_sourced_reply = EventSourcedReply() event_sourced_reply.command_id = command.id event_sourced_reply.client_action.CopyFrom(client_action) snapshot = None perform_snapshot = False if not ctx.has_errors(): for number, event in enumerate(ctx.events): sequence_number = start_sequence_number + number + 1 event_result = handler.handle_event( current_state, event, EventContext(entity_id, start_sequence_number + number), ) if event_result: current_state = event_result snapshot_every = handler.entity.snapshot_every perform_snapshot = (snapshot_every > 0) and ( perform_snapshot or (sequence_number % snapshot_every == 0) ) end_sequence_number = start_sequence_number + len(ctx.events) if perform_snapshot: snapshot = handler.snapshot( current_state, SnapshotContext(entity_id, end_sequence_number), ) event_sourced_reply.side_effects.extend(ctx.effects) event_sourced_reply.events.extend( [pack(event) for event in ctx.events] ) if snapshot: event_sourced_reply.snapshot.Pack(snapshot) output = EventSourcedStreamOut() output.reply.CopyFrom(event_sourced_reply) yield output else: raise Exception( "Cannot handle {} after initialization".format(type(request)) )