Exemplo n.º 1
0
class BrokerEvents(object):
    def __init__(self, broker_uri, management_uri, log_level):
        self.log = Logger(name="BrokerEvents", level=log_level)

        self.log.debug("broker_uri='{}'", broker_uri)
        self.channel = Channel(broker_uri)
        self.subscription = Subscription(self.channel)
        self.subscription.subscribe(topic="binding.*")

        self.log.debug("management_uri='{}'", management_uri)
        self.consumers = self.query_consumers_http(management_uri)

    def run(self):
        while True:
            msg = self.channel.consume()
            self.log.debug("topic='{}' metadata={}", msg.topic, msg.metadata)

            if msg.metadata["destination_kind"] != "queue" or \
               msg.metadata["source_name"] != "is":
                continue

            event = msg.topic.split('.')[-1]
            topic = msg.metadata["routing_key"]
            queue = msg.metadata["destination_name"]

            if event == "created":
                self.consumers.info[topic].consumers.append(queue)
            elif event == "deleted":
                self.consumers.info[topic].consumers.remove(queue)
                if len(self.consumers.info[topic].consumers) == 0:
                    del self.consumers.info[topic]

            self.log.info("event='{}' topic='{}' queue='{}'", event, topic,
                          queue)

            self.channel.publish(
                Message(content=self.consumers),
                topic="BrokerEvents.Consumers",
            )

    @staticmethod
    def query_consumers_http(management_uri):
        reply = requests.get(management_uri + "/api/bindings")
        if reply.status_code != 200:
            why = "Failed to query management API, code={}".format(
                reply.status_code)
            raise RuntimeError(why)

        bindings = reply.json()
        bindings = [
            b for b in bindings
            if b["destination_type"] == "queue" and b["source"] == "is"
        ]

        consumers = ConsumerList()
        for b in bindings:
            consumers.info[b["routing_key"]].consumers.append(b["destination"])
        return consumers
Exemplo n.º 2
0
class RobotGateway(object):
    def __init__(self, driver):
        self.driver = driver
        self.logger = Logger("RobotGateway")

    def get_config(self, field_selector, ctx):
        robot_config = RobotConfig()
        get_obj(self.driver.get_speed, robot_config.speed)
        return robot_config

    def set_config(self, robot_config, ctx):
        if robot_config.HasField("speed"):
            self.driver.set_speed(robot_config.speed)
        return Empty()

    def navigate_to(self, position, ctx):
        self.driver.navigate_to(position.x, position.y)
        return Empty()

    def move_to(self, pose, ctx):
        self.driver.move_to(pose.position.x, pose.position.y,
                            pose.orientation.yaw)
        return Empty()

    def pause_awareness(self, req, ctx):
        self.driver.pause_awareness()
        return Empty()

    def resume_awareness(self, req, ctx):
        self.driver.resume_awareness()
        return Empty()

    def set_awareness(self, req, ctx):
        self.driver.set_awareness(req["enabled"])
        return Empty()

    #def set_awareness_off(self, req, ctx):
    #    self.driver.set_awareness_off()
    #    return Empty()

    def run(self, id, broker_uri):
        service_name = "RobotGateway.{}".format(id)

        channel = Channel(broker_uri)
        server = ServiceProvider(channel)
        logging = LogInterceptor()
        server.add_interceptor(logging)

        server.delegate(topic=service_name + ".GetConfig",
                        request_type=FieldSelector,
                        reply_type=RobotConfig,
                        function=self.get_config)

        server.delegate(topic=service_name + ".SetConfig",
                        request_type=RobotConfig,
                        reply_type=Empty,
                        function=self.set_config)

        server.delegate(topic=service_name + ".NavigateTo",
                        request_type=Position,
                        reply_type=Empty,
                        function=self.navigate_to)

        server.delegate(topic=service_name + ".MoveTo",
                        request_type=Pose,
                        reply_type=Empty,
                        function=self.move_to)

        server.delegate(topic=service_name + ".PauseAwareness",
                        request_type=Empty,
                        reply_type=Empty,
                        function=self.pause_awareness)

        server.delegate(topic=service_name + ".ResumeAwareness",
                        request_type=Empty,
                        reply_type=Empty,
                        function=self.resume_awareness)

        server.delegate(topic=service_name + ".SetAwareness",
                        request_type=Struct,
                        reply_type=Empty,
                        function=self.set_awareness)

        #server.delegate(
        #    topic=service_name + ".SetAwarenessOff",
        #    request_type=Empty,
        #    reply_type=Empty,
        #    function=self.set_awareness_off)

        self.logger.info("Listening for requests")
        while True:
            pose = self.driver.get_base_pose()
            frameTransList = FrameTransformations()
            frameTransList.tfs.extend([pose])
            self.logger.debug("Publishing pose")

            channel.publish(Message(content=frameTransList),
                            topic=service_name + ".FrameTransformations")

            try:
                message = channel.consume(timeout=0)
                if server.should_serve(message):
                    server.serve(message)
            except socket.timeout:
                pass
class RequestManager:
    def __init__(self,
                 channel,
                 max_requests,
                 min_requests=None,
                 log_level=Logger.INFO,
                 zipkin_exporter=None):

        if min_requests is None:
            min_requests = max_requests
        if min_requests < 0:
            min_requests = 0
        if min_requests > max_requests:
            raise Exception("'min_requests' must be lower than 'max_requests'")

        self._channel = channel
        self._subscription = Subscription(self._channel)

        self._do_tracing = zipkin_exporter is not None
        self._zipkin_exporter = zipkin_exporter

        self._log = Logger(name='RequestManager')
        self._log.set_level(level=log_level)

        self._min_requests = min_requests
        self._max_requests = max_requests
        self._can_request = True

        self._requests = {}

    def can_request(self):
        return self._can_request

    def all_received(self):
        return len(self._requests) == 0

    def request(self, content, topic, timeout_ms, metadata=None):

        if not self.can_request():
            raise Exception(
                "Can't request more than {}. Use 'RequestManager.can_request' "
                "method to check if you can do requests.")

        tracer = Tracer(
            exporter=self._zipkin_exporter) if self._do_tracing else None
        span = tracer.start_span(name='request') if self._do_tracing else None

        msg = Message(content=content)
        msg.topic = topic
        msg.reply_to = self._subscription
        msg.timeout = timeout_ms / 1000.0

        self._log.debug("[Sending] metadata={}, cid={}", metadata,
                        msg.correlation_id)

        if self._do_tracing:
            for key, value in (metadata or {}).items():
                span.add_attribute(key, value)
            tracer.end_span()
            msg.inject_tracing(span)

        self._publish(msg, metadata)

        if len(self._requests) >= self._max_requests:
            self._can_request = False

    def consume_ready(self, timeout=1.0):
        received_msgs = []

        # wait for new message
        try:
            stated_at = now()
            while True:
                _timeout = max(0.0, stated_at + timeout - now())
                msg = self._channel.consume(timeout=_timeout)

                if msg.status.ok() and msg.has_correlation_id():
                    cid = msg.correlation_id
                    if cid in self._requests:
                        received_msgs.append(
                            (msg, self._requests[cid]["metadata"]))
                        del self._requests[cid]

        except socket.timeout:
            pass

        # check for timeouted requests
        for cid in self._requests.keys():
            timeouted_msg = self._requests[cid]["msg"]

            if timeouted_msg.deadline_exceeded():
                msg = Message()
                msg.body = timeouted_msg.body
                msg.topic = timeouted_msg.topic
                msg.reply_to = self._subscription
                msg.timeout = timeouted_msg.timeout

                metadata = self._requests[cid]["metadata"]

                del self._requests[cid]

                self._log.debug("[Retring] metadata={}, cid={}", metadata,
                                msg.correlation_id)
                self._publish(msg, metadata)

        if not self._can_request and len(self._requests) <= self._min_requests:
            self._can_request = True

        return received_msgs

    def _publish(self, msg, metadata):
        self._channel.publish(message=msg)
        self._requests[msg.correlation_id] = {
            "msg": msg,
            "metadata": metadata,
        }