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 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 start_actor(): if self._nodeid: Events.log(Message("Setting up remoting; node ID = %s" % (self._nodeid,))) try: f1 = ZmqFactory() insock = ZmqPullConnection(f1) outsock = lambda: ZmqPushConnection(f1, linger=0) hub = Hub(insock, outsock, nodeid=self._nodeid) except Exception: err("Could not set up remoting") traceback.print_exc() reactor.stop() return else: Events.log(Message("No remoting requested; specify `--remoting/-r <nodeid>` (nodeid=host:port) to set up remoting")) hub = HubWithNoRemoting() supervision = {'stop': Stop, 'restart': Restart, 'resume': Resume}[self._supervise] node = Node(hub=hub, root_supervision=supervision) try: self._wrapper = node.spawn(Wrapper.using( self._actor_cls.using(**self._init_params), spawn_at=self._name, keep_running=self._keep_running ), name='_runner') except Exception: panic("Failed to start wrapper for %s\n" % (actor_path,), Failure().getTraceback()) reactor.stop() else: if self._initial_message is not _EMPTY: self._wrapper << ('_forward', self._initial_message)
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 send(self, ref, msg): if self.queue is not None: self.queue.append((ref, msg)) else: if self.sock: self._do_send(dumps((ref.uri.path, msg), protocol=2)) else: Events.log(DeadLetter(ref, msg))
def _send_local(self, msg, ref): cell = self.guardian.lookup_cell(ref.uri) if cell: ref._cell = cell ref.is_local = True ref << msg else: ref.is_local = True # next time, just put it straight to DeadLetters if msg not in (("terminated", ANY), ("_watched", ANY), ("_unwatched", ANY)): Events.log(DeadLetter(ref, msg))
def test_subscribe_and_unsubscribe(): errors = [] Events.subscribe(Error, errors.append) Events.log(Error('actor', 1, 2)) assert errors == [Error('actor', 1, 2)] errors[:] = [] Events.unsubscribe(Error, errors.append) event = Error('actor', 1, 2) Events.log(event) assert errors == []
def test_subscribe_and_unsubscribe(): errors = [] Events.subscribe(UnhandledError, errors.append) Events.log(UnhandledError('actor', 1, 2)) assert errors == [UnhandledError('actor', 1, 2)] errors[:] = [] Events.unsubscribe(UnhandledError, errors.append) event = UnhandledError('actor', 1, 2) Events.log(event) assert errors == []
def receive(self, message): if message == ('_forward', ANY): _, payload = message self.actor << payload elif message == ('terminated', self.actor): _, actor = message if self.keep_running: after(1.0).do(self._do_spawn) else: log("actor terminated but not re-spawning actor; pass --keepruning/-k to change this behaviour") self.stop() else: Events.log(Message("Contained actor sent a message to parent: %r" % (message,)))
def report(self, exc_and_tb=None): if not exc_and_tb: _, exc, tb = sys.exc_info() else: exc, tb = exc_and_tb if not isinstance(exc, UnhandledTermination): if isinstance(tb, str): exc_fmt = tb else: exc_fmt = ''.join(traceback.format_exception(type(exc), exc, tb)) print(exc_fmt.strip(), file=sys.stderr) else: fail("Died because a watched actor (%r) died" % (exc.watchee,)) Events.log(Error(self.ref, exc, tb)),
def receive(self, msg): # dbg("recv %r" % (msg,)) if self.__get_d and self.__get_d.wants(msg): # dbg("injecting %r" % (msg,)) self.__get_d.callback(msg) # dbg("...injectng %r OK" % (msg,)) else: # dbg("queueing") if not self.__queue: self.__queue = [] self.__queue.append(msg) l = len(self.__queue) if l and l % self.hwm == 0: Events.log(HighWaterMarkReached(self.ref, l))
def report(self, exc_and_tb=None): if not exc_and_tb: _, exc, tb = sys.exc_info() else: exc, tb = exc_and_tb if not isinstance(exc, UnhandledTermination): if isinstance(tb, str): exc_fmt = tb else: exc_fmt = ''.join( traceback.format_exception(type(exc), exc, tb)) print(exc_fmt.strip(), file=sys.stderr) else: fail("Died because a watched actor (%r) died" % (exc.watchee, )) Events.log(Error(self.ref, exc, tb)),
def send(self, message, _sender=None): if ('_child_terminated', ANY) == message: _, sender = message self._child_gone(sender) if not self._children and self.all_children_stopped: self.all_children_stopped.set(None) # # XXX: find a better way to avoid Terminated messages for TempActors, # # possibly by using a /tmp container for them # if not str(sender.uri).startswith('/tempactor'): # Events.log(Terminated(sender)) elif message == '_stop': return self._do_stop() elif message == '_kill': return self._do_stop(kill=True) else: if not _sender: context = get_context() if context: _sender = context.ref Events.log(UnhandledMessage(self, message, _sender))
def send(self, message, _sender=None): if ('_child_terminated', ANY) == message: _, sender = message self._child_gone(sender) if not self._children and self.all_children_stopped: self.all_children_stopped.set(None) # # XXX: find a better way to avoid Terminated messages for TempActors, # # possibly by using a /tmp container for them # if not str(sender.uri).startswith('/tempactor'): # Events.log(Terminated(sender)) elif message == '_stop': return self._do_stop() elif message == '_kill': return self._do_stop(kill=True) else: if not _sender: context = get_context() if context: _sender = context.ref Events.log(UnhandledMessage(self, message, _sender))
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))
def _do_spawn(self): self.actor = self.watch(self.node.spawn(self.actor_factory, name=self.spawn_at)) Events.log(Message("Spawned %s" % (self.actor,)))
def _kill_queue(self): q, self.queue = self.queue, None while q: ref, msg = q.popleft() if (IN(["_watched", "_unwatched", "terminated"]), ANY) != msg: Events.log(DeadLetter(ref, msg))
def unhandled(self, m, sender): if ('terminated', ANY) == m: raise UnhandledTermination(watcher=self.ref, watchee=m[1]) else: Events.log(UnhandledMessage(self.ref, m, sender))
def _remote_dead_letter(self, path, msg, from_): uri = Uri.parse(self.nodeid + path) ref = Ref(cell=self.guardian.lookup_cell(uri), uri=uri, is_local=True) Events.log(RemoteDeadLetter(ref, msg, from_))
def send_failed(self): if not (self.msg == ('_unwatched', ANY) or self.msg == ('_watched', ANY)): Events.log(DeadLetter(self.ref, self.msg, self.sender))
def unhandled(self, m, sender): if ('terminated', ANY) == m: raise UnhandledTermination(watcher=self.ref, watchee=m[1]) else: Events.log(UnhandledMessage(self.ref, m, sender))
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))