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")
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")
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")
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")
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")
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")
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")
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 = {}