예제 #1
0
    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))
예제 #2
0
    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))
예제 #3
0
    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))
                )