Ejemplo n.º 1
0
class Publisher(TerminatorBlock):
    """ A block for publishing to a nio communication channel.

    Functions regardless of communication module implementation.

    Properties:
        topic (str): Defines topic to use to publish signals.

    """
    version = VersionProperty('1.0.0')
    topic = StringProperty(title='Topic')

    def __init__(self):
        super().__init__()
        self._publisher = None

    def configure(self, context):
        super().configure(context)
        self._publisher = NioPublisher(topic=self.topic())
        self._publisher.open()

    def stop(self):
        """ Stop the block by closing the underlying publisher """
        self._publisher.close()
        super().stop()

    def process_signals(self, signals):
        """ Publish each list of signals """
        try:
            self._publisher.send(signals)
        except PublisherError:
            self.logger.exception("Error publishing signals")
Ejemplo n.º 2
0
class LocalPublisher(PubSubConnectivity, TerminatorBlock):
    """ A block for publishing to a local nio communication channel.

    Functions regardless of communication module implementation.

    Unlike the regular Publisher block, the one does not need data to be json
    """
    version = VersionProperty("1.1.1")
    topic = StringProperty(title="Topic", default="")
    local_identifier = StringProperty(title='Local Identifier',
                                      default='[[INSTANCE_ID]]',
                                      advanced=True)

    def __init__(self):
        super().__init__()
        self._publisher = None

    def configure(self, context):
        super().configure(context)
        topic = self.topic()
        # If a local identifier was included use it as a prefix
        if self.local_identifier():
            topic = "{}.{}".format(self.local_identifier(), topic)
        self._publisher = NioPublisher(topic=topic)

        try:
            self._publisher.open(on_connected=self.conn_on_connected,
                                 on_disconnected=self.conn_on_disconnected)
        except TypeError as e:
            self.logger.warning(
                "Connecting to an outdated communication module")
            # try previous interface
            self._publisher.open()
            # no need to configure connectivity if not supported
            return

        self.conn_configure(self._publisher.is_connected)

    def stop(self):
        """ Stop the block by closing the underlying publisher """
        self._publisher.close()
        super().stop()

    def process_signals(self, signals):
        """ Publish each list of signals """
        try:
            signals = pickle.dumps(signals)
            signals = [Signal({"signals": b64encode(signals)})]
            self._publisher.send(signals)
        except pickle.PicklingError:
            self.logger.exception("Pickling based pickle error")
        except TypeError:
            self.logger.exception("Unable to encode pickled signals")
        except PublisherError:
            self.logger.exception("Error publishing signals")
        except:
            self.logger.exception("Error processing signals")
Ejemplo n.º 3
0
class LocalPublisher(PubSubConnectivity, TerminatorBlock):
    """ A block for publishing to a local nio communication channel.

    Functions regardless of communication module implementation.

    Unlike the regular Publisher block, the one does not need data to be json
    """
    version = VersionProperty("1.1.1")
    topic = StringProperty(title="Topic", default="")
    local_identifier = StringProperty(
        title='Local Identifier', default='[[INSTANCE_ID]]', advanced=True)

    def __init__(self):
        super().__init__()
        self._publisher = None

    def configure(self, context):
        super().configure(context)
        topic = self.topic()
        # If a local identifier was included use it as a prefix
        if self.local_identifier():
            topic = "{}.{}".format(self.local_identifier(), topic)
        self._publisher = NioPublisher(topic=topic)

        try:
            self._publisher.open(on_connected=self.conn_on_connected,
                                 on_disconnected=self.conn_on_disconnected)
        except TypeError as e:
            self.logger.warning(
                "Connecting to an outdated communication module")
            # try previous interface
            self._publisher.open()
            # no need to configure connectivity if not supported
            return

        self.conn_configure(self._publisher.is_connected)

    def stop(self):
        """ Stop the block by closing the underlying publisher """
        self._publisher.close()
        super().stop()

    def process_signals(self, signals):
        """ Publish each list of signals """
        try:
            signals = pickle.dumps(signals)
            signals = [Signal({"signals": b64encode(signals)})]
            self._publisher.send(signals)
        except pickle.PicklingError:
            self.logger.exception("Pickling based pickle error")
        except TypeError:
            self.logger.exception("Unable to encode pickled signals")
        except PublisherError:
            self.logger.exception("Error publishing signals")
        except:
            self.logger.exception("Error processing signals")
Ejemplo n.º 4
0
    def __create_publisher(self, topic):
        self.logger.info('creating new publisher for "{}"'.format(topic))
        publisher = Publisher(topic=topic)

        try:
            publisher.open(
                on_connected=self.conn_on_connected,
                on_disconnected=self.conn_on_disconnected)
        except TypeError as e:
            self.logger.warning(
                'Connecting to an outdated communication module')
            # try previous interface
            publisher.open()
            # no need to configure connectivity if not supported
            return publisher

        self.conn_configure(publisher.is_connected)
        return publisher
Ejemplo n.º 5
0
class Publisher(PubSubConnectivity, TerminatorBlock):
    """ A block for publishing to a nio communication channel.

    Functions regardless of communication module implementation.

    Properties:
        topic (str): Defines topic to use to publish signals.

    """
    version = VersionProperty("1.1.0")
    topic = StringProperty(title='Topic')

    def __init__(self):
        super().__init__()
        self._publisher = None

    def configure(self, context):
        super().configure(context)
        self._publisher = NioPublisher(topic=self.topic())

        try:
            self._publisher.open(on_connected=self.conn_on_connected,
                                 on_disconnected=self.conn_on_disconnected)
        except TypeError as e:
            self.logger.warning(
                "Connecting to an outdated communication module")
            # try previous interface
            self._publisher.open()
            # no need to configure connectivity if not supported
            return

        self.conn_configure(self._publisher.is_connected)

    def stop(self):
        """ Stop the block by closing the underlying publisher """
        self._publisher.close()
        super().stop()

    def process_signals(self, signals):
        """ Publish each list of signals """
        try:
            self._publisher.send(signals)
        except PublisherError:  # pragma no cover
            self.logger.exception("Error publishing signals")
Ejemplo n.º 6
0
class Publisher(PubSubConnectivity, TerminatorBlock):
    """ A block for publishing to a nio communication channel.

    Functions regardless of communication module implementation.

    Properties:
        topic (str): Defines topic to use to publish signals.

    """
    version = VersionProperty("1.1.1")
    topic = StringProperty(title="Topic", default="")

    def __init__(self):
        super().__init__()
        self._publisher = None

    def configure(self, context):
        super().configure(context)
        self._publisher = NioPublisher(topic=self.topic())

        try:
            self._publisher.open(on_connected=self.conn_on_connected,
                                 on_disconnected=self.conn_on_disconnected)
        except TypeError as e:
            self.logger.warning(
                "Connecting to an outdated communication module")
            # try previous interface
            self._publisher.open()
            # no need to configure connectivity if not supported
            return

        self.conn_configure(self._publisher.is_connected)

    def stop(self):
        """ Stop the block by closing the underlying publisher """
        self._publisher.close()
        super().stop()

    def process_signals(self, signals):
        """ Publish each list of signals """
        try:
            self._publisher.send(signals)
        except PublisherError:  # pragma no cover
            self.logger.exception("Error publishing signals")
Ejemplo n.º 7
0
class LocalPublisher(TerminatorBlock):
    """ A block for publishing to a local nio communication channel.

    Functions regardless of communication module implementation.

    Unlike the regular Publisher block, the one does not need data to be json
    """
    version = VersionProperty("0.1.1")
    topic = StringProperty(title='Topic', default="")
    local_identifier = StringProperty(title='Local Identifier',
                                      default='[[INSTANCE_ID]]',
                                      visible=False)

    def __init__(self):
        super().__init__()
        self._publisher = None

    def configure(self, context):
        super().configure(context)
        self._publisher = NioPublisher(
            topic="{}.{}".format(self.local_identifier(), self.topic()))
        self._publisher.open()

    def stop(self):
        """ Stop the block by closing the underlying publisher """
        self._publisher.close()
        super().stop()

    def process_signals(self, signals):
        """ Publish each list of signals """
        try:
            signals = pickle.dumps(signals)
            signals = [Signal({"signals": b64encode(signals)})]
            self._publisher.send(signals)
        except pickle.PicklingError:
            self.logger.exception("Pickling based pickle error")
        except TypeError:
            self.logger.exception("Unable to encode pickled signals")
        except PublisherError:
            self.logger.exception("Error publishing signals")
        except:
            self.logger.exception("Error processing signals")
Ejemplo n.º 8
0
class Publisher(Block):
    """ A block for publishing to a NIO communication channel.

    Functions regardless of communication module implementation.

    Properties:
        topic (str): Defines topic to use to publish signals.

    """

    topic = StringProperty(title="Topic")

    def __init__(self):
        super().__init__()
        self._publisher = None

    def configure(self, context):
        super().configure(context)
        self._publisher = NIOPublisher(topic=self.topic())
        self._publisher.open()

    def stop(self):
        """ Stop the block by closing the underlying publisher

        """
        self._publisher.close()
        super().stop()

    def process_signals(self, signals):
        """ Publisher block doesn't do any real processing, just publishes
        the signals it processes.

        """
        try:
            self._publisher.send(signals)
        except PublisherError:
            self.logger.exception("Error publishing signals")
Ejemplo n.º 9
0
class StatsRouter(BaseBlockRouter):
    """ A router that provides stats on the number of signals received
    by a block.

    """

    def __init__(self):
        super().__init__()
        self._executor = None
        self._service_name = ""
        self._blocks = {}
        self._blocks_lock = RLock()
        self._job = None
        self._stats_timeout = None
        self._publisher = None

    def configure(self, context):
        super().configure(context)

        # TODO: consider adding service name to base router
        # grab service name, the best way possible, in this case, from
        # first block controller with a meaningful name (BTW, they all should
        # have the same name)
        for block_name, block_controller in context.blocks.items():
            if block_controller._service_name:
                self._service_name = block_controller._service_name
                break

        # attempt to pick up configuration file from etc folder
        conf = Configuration("block_router.cfg")
        # grab some config parameters
        self._stats_timeout = conf.get("stats_timeout", 1)

        # create stats publisher
        self._publisher = Publisher(**conf.get("stats_topics",
                                               {"type": "wiretap"}))

    def start(self):
        super().start()
        self._publisher.open()

        # create publishing repeatable job
        self._job = Job(self._deliver_stats,
                        timedelta(seconds=self._stats_timeout), True)

    def stop(self):
        if self._job:
            self._job.cancel()
            self._job = None

        self._publisher.close()
        super().stop()

    def deliver_signals(self, block, signals, input_id):
        # do normal routing
        super().deliver_signals(block, signals, input_id)

        # update stats
        with self._blocks_lock:
            if block.name not in self._blocks:
                self._blocks[block.name] = 0
            self._blocks[block.name] += len(signals)

    def _deliver_stats(self):
        with self._blocks_lock:
            self._publisher.send(Signal({"service_name": self._service_name,
                                         "block_stats": self._blocks}))
            self._blocks = {}