def _run(self): """ The actor's main method. :class:`pykka.gevent.GeventActor` expects this method to be named :meth:`_run`. :class:`ThreadingActor` expects this method to be named :meth:`run`. """ self.on_start() while self._actor_runnable: try: message = self.actor_inbox.get(False) _logger.debug('Actor {} got message {}'.format(self, message)) try: response = self._handle_receive(message) if 'reply_to' in message: message['reply_to'].set(response) except Exception as exception: if 'reply_to' in message: _logger.debug('Exception returned from %s to caller:' % self, exc_info=_sys.exc_info()) message['reply_to'].set_exception(exception) else: self._handle_failure(*_sys.exc_info()) except BaseException as exception: exception_value = _sys.exc_info()[1] _logger.debug('%s in %s. Stopping all actors.' % (repr(exception_value), self)) self.stop() _ActorRegistry.stop_all() except _queue.Empty: pass
def _actor_loop(self): """ The actor's event loop. This is the method that will be executed by the thread or greenlet. """ self.on_start() while self._actor_runnable: message = self.actor_inbox.get() try: response = self._handle_receive(message) if 'reply_to' in message: message['reply_to'].set(response) except Exception: if 'reply_to' in message: _logger.debug( 'Exception returned from %s to caller:' % self, exc_info=_sys.exc_info()) message['reply_to'].set_exception() else: self._handle_failure(*_sys.exc_info()) except BaseException: exception_value = _sys.exc_info()[1] _logger.debug( '%s in %s. Stopping all actors.' % (repr(exception_value), self)) self._stop() _ActorRegistry.stop_all()
def scan_command(directory, tagfile='STAG.sqlite', verbose=False): """Scan a directory tree for definitions and references.""" init_logging(verbose) with StorageManager(Storage(tagfile)) as s: s.clear_defs() storage = StorageActor.start(s) parser_map = [ (list(p.patterns()), ParserActor.start(p.create_parser(), storage)) for p in parser_plugins()] dispatcher = DispatcherActor.start(parser_map) def dispatch_file(args): "Send results of os.walk to the dispatcher." dirpath, _, filenames = args for fname in filenames: dispatcher.tell({ 'command': 'dispatch', 'filename': os.path.join(dirpath, fname) }) emap(dispatch_file, os.walk(directory)) # Shut everything down. ActorRegistry.stop_all()
def start(cls, *args, **kwargs): """ Start an actor and register it in the :class:`pykka.registry.ActorRegistry`. Any arguments passed to :meth:`start` will be passed on to the class constructor. Returns a :class:`ActorRef` which can be used to access the actor in a safe manner. Behind the scenes, the following is happening when you call :meth:`start`:: Actor.start() Actor.__new__() superclass.__new__() superclass.__init__() URN assignment Inbox creation ActorRef creation Actor.__init__() # Your code can run here ActorRegistry.register() superclass.start() """ obj = cls(*args, **kwargs) _ActorRegistry.register(obj.actor_ref) cls._superclass.start(obj) _logger.debug('Started %s', obj) return obj.actor_ref
def _handle_failure(self, exception_type, exception_value, traceback): """Logs unexpected failures, unregisters and stops the actor.""" _logger.error('Unhandled exception in %s:' % self, exc_info=(exception_type, exception_value, traceback)) _ActorRegistry.unregister(self.actor_ref) self._actor_runnable = False self.on_failure(exception_type, exception_value, traceback)
def _handle_failure(self, exception_type, exception_value, traceback): """Logs unexpected failures, unregisters and stops the actor.""" logger.error( 'Unhandled exception in %s:' % self, exc_info=(exception_type, exception_value, traceback)) ActorRegistry.unregister(self.actor_ref) self.actor_stopped.set()
def _stop(self): """ Stops the actor immediately without processing the rest of the inbox. """ _ActorRegistry.unregister(self.actor_ref) self._actor_runnable = False _logger.debug('Stopped %s', self) self.on_stop()
def test_broadcast_sends_message_to_all_actors_of_given_class_name(self): ActorRegistry.broadcast({'command': 'foo'}, target_class='AnActor') for actor_ref in ActorRegistry.get_by_class(self.AnActor): received_messages = actor_ref.proxy().received_messages.get() self.assert_({'command': 'foo'} in received_messages) for actor_ref in ActorRegistry.get_by_class(self.BeeActor): received_messages = actor_ref.proxy().received_messages.get() self.assert_({'command': 'foo'} not in received_messages)
def setup(self): audio_refs = ActorRegistry.get_by_class(audio.Audio) assert len(audio_refs) == 1, \ 'Expected exactly one running Audio instance.' self.audio = audio_refs[0].proxy() backend_refs = ActorRegistry.get_by_class(Backend) assert len(backend_refs) == 1, 'Expected exactly one running backend.' self.backend = backend_refs[0].proxy()
def setup(self): gstreamer_refs = ActorRegistry.get_by_class(GStreamer) assert len(gstreamer_refs) == 1, \ 'Expected exactly one running gstreamer.' self.gstreamer = gstreamer_refs[0].proxy() backend_refs = ActorRegistry.get_by_class(Backend) assert len(backend_refs) == 1, 'Expected exactly one running backend.' self.backend = backend_refs[0].proxy()
def stop(self): logger.info("exiting ...") logger.info("waiting for actors to stop ...") try: ActorRegistry.stop_all(timeout=10) except Exception as ex: logger.info("warning - actors failed to stop cleanly") logger.info("stopping web server ...") stop_web() logger.info("finished")
def stop(self): """ Stop the actor. The actor will finish processing any messages already in its queue before stopping. It may not be restarted. """ self.actor_runnable = False ActorRegistry.unregister(self.actor_ref) logger.debug(u'Stopped %s', self)
def stop_all_actors(): num_actors = len(ActorRegistry.get_all()) while num_actors: logger.debug(u'Seeing %d actor and %d non-actor thread(s): %s', num_actors, threading.active_count() - num_actors, ', '.join([t.name for t in threading.enumerate()])) logger.debug(u'Stopping %d actor(s)...', num_actors) ActorRegistry.stop_all() num_actors = len(ActorRegistry.get_all()) logger.debug(u'All actors stopped.')
def test_actor_may_be_unregistered_multiple_times_without_error(self): ActorRegistry.unregister(self.ref) self.assert_(self.ref not in ActorRegistry.get_all()) ActorRegistry.unregister(self.ref) self.assert_(self.ref not in ActorRegistry.get_all()) ActorRegistry.register(self.ref) self.assert_(self.ref in ActorRegistry.get_all())
def _stop(self): """ Stops the actor immediately without processing the rest of the inbox. """ _ActorRegistry.unregister(self.actor_ref) self._actor_runnable = False _logger.debug('Stopped %s', self) try: self.on_stop() except Exception: self._handle_failure(*_sys.exc_info())
def stop_remaining_actors(): num_actors = len(ActorRegistry.get_all()) while num_actors: logger.error( u'There are actor threads still running, this is probably a bug') logger.debug(u'Seeing %d actor and %d non-actor thread(s): %s', num_actors, threading.active_count() - num_actors, ', '.join([t.name for t in threading.enumerate()])) logger.debug(u'Stopping %d actor(s)...', num_actors) ActorRegistry.stop_all() num_actors = len(ActorRegistry.get_all()) logger.debug(u'All actors stopped.')
def test_runs_parallel(self): self.actor = CoroutineActor.start().proxy() first = self.actor.infinite_loop_count.get() self.actor.loop_infinitely(0).get() second = self.actor.infinite_loop_count.get() self.actor.other_method().get() called = self.actor.other_called.get() third = self.actor.infinite_loop_count.get() self.assertTrue(called) self.assertLess(first, second) self.assertLess(second, third) ActorRegistry.stop_all()
def _actor_loop(self): """ The actor's event loop. This is the method that will be executed by the thread or greenlet. """ try: self.on_start() except Exception: self._handle_failure(*sys.exc_info()) while not self.actor_stopped.is_set(): message = self.actor_inbox.get() reply_to = None try: reply_to = message.pop('pykka_reply_to', None) response = self._handle_receive(message) if reply_to: reply_to.set(response) except Exception: if reply_to: logger.debug( 'Exception returned from %s to caller:' % self, exc_info=sys.exc_info()) reply_to.set_exception() else: self._handle_failure(*sys.exc_info()) try: self.on_failure(*sys.exc_info()) except Exception: self._handle_failure(*sys.exc_info()) except BaseException: exception_value = sys.exc_info()[1] logger.debug( '%s in %s. Stopping all actors.' % (repr(exception_value), self)) self._stop() ActorRegistry.stop_all() while not self.actor_inbox.empty(): msg = self.actor_inbox.get() reply_to = msg.pop('pykka_reply_to', None) if reply_to: if msg.get('command') == 'pykka_stop': reply_to.set(None) else: reply_to.set_exception(ActorDeadError( '%s stopped before handling the message' % self.actor_ref))
def run(pool_size, *ips): # Start resolvers resolvers = [Resolver.start_proxy() for _ in range(pool_size)] # Distribute work by mapping IPs to resolvers (not blocking) hosts = [] for i, ip in enumerate(ips): hosts.append(resolvers[i % len(resolvers)].resolve(ip)) # Gather results (blocking) ip_to_host = zip(ips, get_all(hosts)) pprint(ip_to_host) # Clean up ActorRegistry.stop_all()
def test_all_actors_are_stopped_on_base_exception(self): start_event = self.event_class() stop_event = self.event_class() fail_event = self.event_class() registered_event = self.event_class() another_actor = self.AnActor.start(start_event, stop_event, fail_event, registered_event) self.assertEqual(2, len(ActorRegistry.get_all())) self.assertFalse(self.on_stop_was_called.is_set()) self.actor_ref.send_one_way({'command': 'raise base exception'}) self.on_stop_was_called.wait() self.assert_(1 >= len(ActorRegistry.get_all())) stop_event.wait() self.assertEqual(0, len(ActorRegistry.get_all()))
def backend(self): if self._backend is None: backend_refs = ActorRegistry.get_by_class(Backend) assert len(backend_refs) == 1, \ 'Expected exactly one running backend.' self._backend = backend_refs[0].proxy() return self._backend
def on_start(self): gstreamer_refs = ActorRegistry.get_by_class(GStreamer) assert len(gstreamer_refs) == 1, 'Expected exactly one running gstreamer.' self.gstreamer = gstreamer_refs[0].proxy() logger.info(u'Mopidy uses SPOTIFY(R) CORE') self.spotify = self._connect()
def on_start(self): audio_refs = ActorRegistry.get_by_class(audio.Audio) assert len(audio_refs) == 1, \ 'Expected exactly one running Audio instance.' self.audio = audio_refs[0].proxy() logger.info(u'Mopidy uses SPOTIFY(R) CORE') self.spotify = self._connect()
def test_stop_all_stops_last_started_actor_first_if_blocking( self, mock_method): stopped_actors = [] started_actors = [mock.Mock(name=i) for i in range(3)] started_actors[0].stop.side_effect = lambda *a, **kw: \ stopped_actors.append(started_actors[0]) started_actors[1].stop.side_effect = lambda *a, **kw: \ stopped_actors.append(started_actors[1]) started_actors[2].stop.side_effect = lambda *a, **kw: \ stopped_actors.append(started_actors[2]) ActorRegistry.get_all.return_value = started_actors ActorRegistry.stop_all(block=True) self.assertEqual(stopped_actors[0], started_actors[2]) self.assertEqual(stopped_actors[1], started_actors[1]) self.assertEqual(stopped_actors[2], started_actors[0])
def _notify_backend_of_eos(self): backend_refs = ActorRegistry.get_by_class(Backend) assert len(backend_refs) <= 1, 'Expected at most one running backend.' if backend_refs: logger.debug(u'Notifying backend of end-of-stream.') backend_refs[0].proxy().playback.on_end_of_track() else: logger.debug(u'No backend to notify of end-of-stream found.')
def test_actor_processes_all_messages_before_stop_on_self_stops_it(self): self.actor_ref.ask({'command': 'message self then stop'}) self.greetings_was_received.wait(5) self.assertTrue(self.greetings_was_received.is_set()) self.on_stop_was_called.wait(5) self.assertEqual(0, len(ActorRegistry.get_all()))
def mixer(self): """ The mixer. An instance of :class:`mopidy.mixers.base.BaseMixer`. """ if self._mixer is None: mixer_refs = ActorRegistry.get_by_class(BaseMixer) assert len(mixer_refs) == 1, 'Expected exactly one running mixer.' self._mixer = mixer_refs[0].proxy() return self._mixer
def backend(self): """ The backend. An instance of :class:`mopidy.backends.base.Backend`. """ if self._backend is None: backend_refs = ActorRegistry.get_by_class(Backend) assert len(backend_refs) == 1, 'Expected exactly one running backend.' self._backend = backend_refs[0].proxy() return self._backend
def tell(self, message, safe=False): """ Send message to actor without waiting for any response. Will generally not block, but if the underlying queue is full it will block until a free slot is available. :param message: message to send :type message: picklable dict :raise: :exc:`pykka.ActorDeadError` if actor is not available :return: nothing """ if not self.is_alive(): if safe: ActorRegistry.broadcast(DeadMessage(self, message), DeadMessageBox) else: raise ActorDeadError('%s not found' % self) self.actor_inbox.put(message)
def is_alive(self): """ Check if actor is alive. This is based on whether the actor is registered in the actor registry or not. The actor is not guaranteed to be alive and responding even though :meth:`is_alive` returns :class:`True`. :return: Returns :class:`True` if actor is alive, :class:`False` otherwise. """ return _ActorRegistry.get_by_urn(self.actor_urn) is not None
def start(cls, *args, **kwargs): """ Start an actor and register it in the :class:`ActorRegistry <pykka.ActorRegistry>`. Any arguments passed to :meth:`start` will be passed on to the class constructor. Behind the scenes, the following is happening when you call :meth:`start`: 1. The actor is created: 1. :attr:`actor_urn` is initialized with the assigned URN. 2. :attr:`actor_inbox` is initialized with a new actor inbox. 3. :attr:`actor_ref` is initialized with a :class:`pykka.ActorRef` object for safely communicating with the actor. 4. At this point, your :meth:`__init__()` code can run. 2. The actor is registered in :class:`pykka.ActorRegistry`. 3. The actor receive loop is started by the actor's associated thread/greenlet. :returns: a :class:`ActorRef` which can be used to access the actor in a safe manner """ obj = cls(*args, **kwargs) assert obj.actor_ref is not None, ( 'Actor.__init__() have not been called. ' 'Did you forget to call super() in your override?') _ActorRegistry.register(obj.actor_ref) _logger.debug('Starting %s', obj) # pylint: disable = W0212 obj._start_actor_loop() # pylint: enable = W0212 return obj.actor_ref
def test_all_actors_are_stopped_on_base_exception(self): start_event = self.event_class() stop_event = self.event_class() fail_event = self.event_class() registered_event = self.event_class() greetings_event = self.event_class() self.AnActor.start( on_start_was_called=start_event, on_stop_was_called=stop_event, on_failure_was_called=fail_event, actor_was_registered_before_on_start_was_called=registered_event, greetings_was_received=greetings_event) self.assertEqual(2, len(ActorRegistry.get_all())) self.assertFalse(self.on_stop_was_called.is_set()) self.actor_ref.tell({'command': 'raise base exception'}) self.on_stop_was_called.wait(5) self.assertTrue(self.on_stop_was_called.is_set()) self.assert_(1 >= len(ActorRegistry.get_all())) stop_event.wait(5) self.assertTrue(stop_event.is_set()) self.assertEqual(0, len(ActorRegistry.get_all()))
def _actor_loop(self): """ The actor's event loop. This is the method that will be executed by the thread or greenlet. """ try: self.on_start() except Exception: self._handle_failure(*_sys.exc_info()) while self._actor_runnable: message = self.actor_inbox.get() try: response = self._handle_receive(message) if 'reply_to' in message: message['reply_to'].set(response) except Exception: if 'reply_to' in message: _logger.debug( 'Exception returned from %s to caller:' % self, exc_info=_sys.exc_info()) message['reply_to'].set_exception() else: self._handle_failure(*_sys.exc_info()) try: self.on_failure(*_sys.exc_info()) except Exception: self._handle_failure(*_sys.exc_info()) except BaseException: exception_value = _sys.exc_info()[1] _logger.debug( '%s in %s. Stopping all actors.' % (repr(exception_value), self)) self._stop() _ActorRegistry.stop_all()
def test_all_actors_can_be_stopped_through_registry(self): self.assertEquals(9, len(ActorRegistry.get_all())) ActorRegistry.stop_all(block=True) self.assertEquals(0, len(ActorRegistry.get_all()))
def tearDown(self): ActorRegistry.stop_all() shutil.rmtree(self.tmp_share_dir)
def test_actor_is_stopped_when_unhandled_exceptions_are_raised(self): self.assertFalse(self.on_failure_was_called.is_set()) self.actor_ref.tell({'command': 'raise exception'}) self.on_failure_was_called.wait(5) self.assertTrue(self.on_failure_was_called.is_set()) self.assertEqual(0, len(ActorRegistry.get_all()))
def tearDown(self): ActorRegistry.stop_all()
def on_start(self): gstreamer_refs = ActorRegistry.get_by_class(GStreamer) assert len(gstreamer_refs) == 1, \ 'Expected exactly one running GStreamer.' self.gstreamer = gstreamer_refs[0].proxy()
def test_actor_is_registered_when_started(self): self.assert_(self.ref in ActorRegistry.get_all())
def test_actor_is_unregistered_when_stopped(self): self.assert_(self.ref in ActorRegistry.get_all()) self.ref.stop() self.assert_(self.ref not in ActorRegistry.get_all())
def tearDown(self): ActorRegistry.stop_all() self.mockedSocket.stop()
def _handle_failure(self, exception_type, exception_value, traceback): """Logs unexpected failures, unregisters and stops the actor.""" logger.error('Unhandled exception in %s:' % self, exc_info=(exception_type, exception_value, traceback)) ActorRegistry.unregister(self.actor_ref) self.actor_stopped.set()
def OnExit(self): ActorRegistry.stop_all()
def exit_status(exit_code): settings_listener.stop() ActorRegistry.stop_all() return exit_code
def tearDown(self): self.log_handler.close() ActorRegistry.stop_all()
def number_of_connections(self): return len(ActorRegistry.get_by_class(self.protocol))
def stop_actors_by_class(klass): actors = ActorRegistry.get_by_class(klass) logger.debug(u'Stopping %d instance(s) of %s', len(actors), klass.__name__) for actor in actors: actor.stop()
def test_actor_may_be_registered_manually(self): ActorRegistry.unregister(self.ref) self.assert_(self.ref not in ActorRegistry.get_all()) ActorRegistry.register(self.ref) self.assert_(self.ref in ActorRegistry.get_all())
def test_broadcast_sends_message_to_all_actors_if_no_target(self): ActorRegistry.broadcast({'command': 'foo'}) for actor_ref in ActorRegistry.get_all(): received_messages = actor_ref.proxy().received_messages.get() self.assert_({'command': 'foo'} in received_messages)
def on_start(self): audio_refs = ActorRegistry.get_by_class(audio.Audio) assert len(audio_refs) == 1, \ 'Expected exactly one running Audio instance.' self.audio = audio_refs[0].proxy()
#! /usr/bin/env python from pykka.actor import ThreadingActor from pykka.registry import ActorRegistry class Adder(ThreadingActor): def add_one(self, i): print '%s is increasing %d' % (self, i) return i + 1 class Bookkeeper(ThreadingActor): def __init__(self, adder): self.adder = adder def count_to(self, target): i = 0 while i < target: i = self.adder.add_one(i).get() print '%s got %d back' % (self, i) if __name__ == '__main__': adder = Adder.start().proxy() bookkeeper = Bookkeeper.start(adder).proxy() bookkeeper.count_to(10).get() ActorRegistry.stop_all()
def mixer(self): if self._mixer is None: mixer_refs = ActorRegistry.get_by_class(BaseMixer) assert len(mixer_refs) == 1, 'Expected exactly one running mixer.' self._mixer = mixer_refs[0].proxy() return self._mixer
def test_get_by_urn_returns_none_if_not_found(self): result = ActorRegistry.get_by_urn('urn:foo:bar') self.assertEqual(None, result)
def tearDown(self): self.mocked_server.stop() ActorRegistry.stop_all() shutil.rmtree(self.share_dir)
def test_actors_may_be_looked_up_by_urn(self): result = ActorRegistry.get_by_urn(self.a_actor_0_urn) self.assertEqual(self.a_actors[0], result)
def on_start(self): self.on_start_was_called.set() if ActorRegistry.get_by_urn(self.actor_urn) is not None: self.actor_was_registered_before_on_start_was_called.set()
def test_actors_may_be_looked_up_by_class_name(self): result = ActorRegistry.get_by_class_name('AnActor') for a_actor in self.a_actors: self.assert_(a_actor in result) for b_actor in self.b_actors: self.assert_(b_actor not in result)
def on_start(self): output_refs = ActorRegistry.get_by_class(GStreamer) assert len(output_refs) == 1, 'Expected exactly one running output.' self.output = output_refs[0].proxy()
def test_actors_may_be_looked_up_by_superclass(self): result = ActorRegistry.get_by_class(AnActorSuperclass) for a_actor in self.a_actors: self.assert_(a_actor in result) for b_actor in self.b_actors: self.assert_(b_actor not in result)