def test_all_stashed_messages_are_reported_as_unhandled_on_flush_and_discarded( defer): class MyProc(Actor): def run(self): self.get('dummy') self.flush() self.get('dummy') self.flush() node = DummyNode() defer(node.stop) p = node.spawn(MyProc) p << 'should-be-reported-as-unhandled' with expect_event_not_emitted( DeadLetter(p, 'should-be-reported-as-unhandled', sender=None)): with expect_one_event( UnhandledMessage(p, 'should-be-reported-as-unhandled', sender=None)): p << 'dummy' with expect_event_not_emitted( DeadLetter(p, 'should-be-reported-as-unhandled', sender=None)): with expect_event_not_emitted( UnhandledMessage(p, 'should-be-reported-as-unhandled', sender=None)): p << 'dummy'
def test_dead_letters_are_emitted_in_the_order_the_messages_were_sent(defer): node = DummyNode() defer(node.stop) a = node.spawn(Actor) with expect_one_event(DeadLetter(a, 'dummy1', sender=None)): with expect_one_event(DeadLetter(a, 'dummy2', sender=None)): a << 'dummy1' << 'dummy2' a.stop()
def _remote_dead_letter(self, path, msg, sender): ref = Ref(cell=None, uri=Uri.parse(self.nid + path), node=self, is_local=True) if not (msg == ('_unwatched', ANY) or msg == ('_watched', ANY)): Events.log(DeadLetter(ref, msg, sender))
def destroy(self): if self._ref and self._ref(): ref = self._ref( ) # grab the ref before we stop, otherwise ref() returns a dead ref self.stopped = True ref._cell = None self._ref = None else: self.stopped = True ref = self.ref while True: try: sender, m = self.queue.get_nowait() except gevent.queue.Empty: break if m == ('_watched', ANY): self._watched(m[1]) elif m == ('__error', ANY, ANY): _, exc, tb = m self.report((exc, tb)) elif not (m == ('terminated', ANY) or m == ('_unwatched', ANY) or m == ('_node_down', ANY) or m == '_stop' or m == '_kill' or m == '__done' or m == '__undone'): Events.log(DeadLetter(ref, m, sender)) self.parent_actor.send(('_child_terminated', ref)) for watcher in (self.watchers or []): watcher << ('terminated', ref) self.actor = self.inbox = self.queue = self.parent_actor = None
def receive(self, message): eq_(message, ('terminated', watchee)) _, sender = message with expect_one_event(DeadLetter(sender, 'dummy', sender=self.ref)): sender << 'dummy' idle() all_ok.set()
def test_queued_messages_are_logged_as_deadletters_after_stop(defer): node = DummyNode() defer(node.stop) deadletter_event_emitted = Events.consume_one(DeadLetter) a = node.spawn(Actor) a.stop() a << 'dummy' eq_(deadletter_event_emitted.get(), DeadLetter(a, 'dummy', sender=None))
def test_messages_to_dead_actors_are_sent_to_dead_letters(defer): node = DummyNode() defer(node.stop) a = node.spawn(Actor) a.stop() with expect_one_event(DeadLetter(a, 'should-end-up-as-letter', sender=None)): a << 'should-end-up-as-letter' idle()
def test_sending_to_an_unknown_node_doesnt_start_if_the_node_doesnt_become_visible_and_the_message_is_later_dropped( defer): sender_node = Node('localhost:20001', enable_remoting=True, hub_kwargs={ 'heartbeat_interval': 0.05, 'heartbeat_max_silence': 0.1 }) defer(sender_node.stop) ref = sender_node.lookup_str('localhost:23456/actor2') with expect_one_event(DeadLetter(ref, 'bar', sender=None)): ref << 'bar'
def test_stopping_in_pre_start_directs_any_refs_to_deadletters(defer): class MyActor(Actor): def pre_start(self): self.stop() def receive(self, message): message_received.set() node = DummyNode() defer(node.stop) message_received = Event() a = node.spawn(MyActor) with expect_one_event(DeadLetter(a, 'dummy', sender=None)): a << 'dummy' ok_(not message_received.is_set())
def test_sending_message_to_stopping_parent_from_post_stop_should_deadletter_the_message( defer): class Parent(Actor): def pre_start(self): self.spawn(Child) def receive(self, message): ok_(False) class Child(Actor): def post_stop(self): self._parent << 'should-not-be-received' node = DummyNode() defer(node.stop) p = node.spawn(Parent) with expect_one_event(DeadLetter(ANY, ANY, sender=ANY)): p.stop() idle()
def test_stopping_an_actor_prevents_it_from_processing_any_more_messages( defer): class MyActor(Actor): def receive(self, _): received.set() node = DummyNode() defer(node.stop) received = Event() a = node.spawn(MyActor) a << None received.wait() received.clear() a.stop() sleep(.001) ok_(not received.is_set(), "the '_stop' message should not be receivable in the actor") with expect_one_event(DeadLetter(a, None, sender=None)): a << None
def send(self, message, _sender=None): """Sends a message to the actor represented by this `Ref`.""" if not _sender: context = get_context() if context: _sender = context.ref if self._cell: if not self._cell.stopped: self._cell.receive(message, _sender) return else: self._cell = None if not self.is_local: if self.uri.node != self.node.nid: self.node.send_message(message, remote_ref=self, sender=_sender) else: self._cell = self.node.guardian.lookup_cell(self.uri) self.is_local = True self._cell.receive(message, _sender) else: if self.node and self.node.guardian: cell = self.node.guardian.lookup_cell(self.uri) if cell: cell.receive( message, _sender ) # do NOT set self._cell--it will never be unset and will cause a memleak return if ('_watched', ANY) == message: message[1].send(('terminated', self), _sender=self) elif (message == ('terminated', ANY) or message == ('_unwatched', ANY) or message == ('_node_down', ANY) or message == '_stop' or message == '_kill' or message == '__done'): pass else: Events.log(DeadLetter(self, message, _sender))
def send_failed(self): if not (self.msg == ('_unwatched', ANY) or self.msg == ('_watched', ANY)): Events.log(DeadLetter(self.ref, self.msg, self.sender))