def post_msg(self, target: str, msg, prio: int = None, on_error=None): """ Post a message. Notes ----- This method should always be used when sending a message. The computation should never use the `_msg_sender` directly has this would bypass the pause state. Parameters ---------- target: str the target computation for the message msg: an instance of Message the message to send prio: int priority level on_error: error handling method passed to the messaging component. """ if not self.is_paused: self._msg_sender(self.name, target, msg, prio, on_error) event_bus.send("computations.message_snd." + self.name, (self.name, msg.size)) else: self._paused_messages_post.append((target, msg, prio, on_error))
def test_simple_send(event_bus): cb = MagicMock() event_bus.subscribe("evt-name", cb) event_bus.send("evt-name", 42) cb.assert_called_once_with("evt-name", 42)
def test_several_subscribers(event_bus): cb1 = event_bus.subscribe("evt-name", MagicMock()) cb2 = event_bus.subscribe("evt-name", MagicMock()) cb3 = event_bus.subscribe("evt-name", MagicMock()) event_bus.send("evt-name", 42) cb1.assert_called_once_with("evt-name", 42) cb2.assert_called_once_with("evt-name", 42) cb3.assert_called_once_with("evt-name", 42)
def new_cycle(self): """ For algorithms that have a concept of cycle, you must call this method (in the subclass) at the start of every new cycle. This is used to generate statistics by cycles. Notes ----- You can just ignore this if you do not care about cycles. """ self.__cycle_count__ += 1 self._on_new_cycle(self.cycle_count) event_bus.send("computations.cycle." + self.name, (self.name, self.cycle_count))
def test_do_not_receive_evt_once_unsubscribed(event_bus): cb = MagicMock() event_bus.subscribe("evts", cb) event_bus.send("evts", 42) cb.assert_called_once_with("evts", 42) cb.reset_mock() event_bus.unsubscribe(cb) event_bus.send("evts", 43) cb.assert_not_called()
def test_unsubscribe_from_single_topic(event_bus): cb1 = event_bus.subscribe("evts", MagicMock()) cb2 = event_bus.subscribe("evts", MagicMock()) event_bus.send("evts", 42) cb1.assert_called_once_with("evts", 42) cb2.assert_called_once_with("evts", 42) cb1.reset_mock() cb2.reset_mock() event_bus.unsubscribe(cb2) event_bus.send("evts", 43) cb1.assert_called_once_with("evts", 43) cb2.assert_not_called()
def value_selection(self, val, cost=0): """ When the computation selects a value, it MUST be done by calling this method. This is necessary to be able to automatically monitor value changes. :param val: :param cost: """ if val != self._previous_val: self.logger.info( "Selecting new value: %s, %s (previous: %s, %s)", val, cost, self._previous_val, self.__cost__, ) self._on_value_selection(val, cost, self.cycle_count) self._previous_val = val self.__value__ = val event_bus.send("computations.value." + self.name, (self.name, val)) self.__cost__ = cost
def on_message(self, sender: str, msg: Message, t: float): """ This method is called by the hosting agent when a message for this computation object has been received. Notes ----- Subclasses of :class:`MessagePassingComputation` should not override this method, as it is used for storing received messages during pause. Instead, they should register a method for each message type by using the :func:`register` decorator. Parameters ---------- sender: str the name of the computation that has sent this msg: an instance of Message the received message that must be handled t: float reception time """ if not self.is_paused and self._running: # Only handle messages if the computation has been started and is # not paused. event_bus.send( "computations.message_rcv." + self.name, (self.name, msg.size) ) try: self._decorated_handlers[msg.type](self, sender, msg, t) except KeyError: self._msg_handlers[msg.type](sender, msg, t) else: self.logger.debug( f"Storing message from {sender} {msg} . " f"paused {self.is_paused}, running {self._running}" ) self._paused_messages_recv.append((sender, msg, t))
def test_receive_evt_from_sub_topics(event_bus): cb1 = event_bus.subscribe("a.b.*", MagicMock()) # Event on sub-topic : must be received event_bus.send("a.b.c", 42) cb1.assert_called_once_with("a.b.c", 42) # Event on another topic : must not be received cb1.reset_mock() event_bus.send("a.another.d.f", 42) cb1.assert_not_called() # Event on another topic : must not be received cb1.reset_mock() event_bus.send("a.bb.f", 42) cb1.assert_not_called()
def test_cb_not_called_when_not_subscribed(event_bus): cb = MagicMock() event_bus.send("another", 48) cb.assert_not_called()