class NBServerTask(VTask): DEFAULT_HOST = '0.0.0.0' DEFAULT_PORT = 0 OPT_PREFIX = 'thrift' bound_host = bound_port = None def getProcessor(self): """Automatically find the ThriftProcessorTask subclass""" found = None for task in self.service.tasks: if isinstance(task, ThriftProcessorTask): assert found is None, "Multiple processor tasks! (%s, %s)" % \ (found.name, task.name) found = task assert found is not None, "No ThriftProcessorTask's found!" return found.processor def initTask(self): super(NBServerTask, self).initTask() self._stopped = False self.socket = TServerSocket( self.getTaskOption('host'), self.getTaskOption('port')) self.server = TNonblockingServer( self.getProcessor(), self.socket, threads=self.getTaskOption('threads')) self.server.prepare() self.bound_host, self.bound_port = \ self.server.socket.handle.getsockname() self.logger.info("%s Server Started on %s:%s", self.name, self.bound_host, self.bound_port) def stop(self): self.server.stop() self.server.close() self._stopped = True def _runloop(self): while not self.server._stop: self.server.serve() while not self._stopped: time.sleep(0.1) @classmethod def _addArguments(cls, ap): super(NBServerTask, cls)._addArguments(ap) ap.add_argument(cls._loptName('host'), default=cls.DEFAULT_HOST, metavar='HOST', help='Address to bind server to [%(default)s]') ap.add_argument(cls._loptName('port'), type=int, metavar='PORT', default=cls.DEFAULT_PORT, help='Port to run server on [%(default)s]') ap.add_argument(cls._loptName('threads'), type=int, default=10, metavar='N', help='Server Worker Threads [%(default)s]')
class NBServerTask(ThriftServerTask): """Spin up a thrift TNonblockingServer in a sparts worker thread""" DEFAULT_HOST = '0.0.0.0' DEFAULT_PORT = 0 OPT_PREFIX = 'thrift' bound_host = bound_port = None host = option(default=lambda cls: cls.DEFAULT_HOST, metavar='HOST', help='Address to bind server to [%(default)s]') port = option(default=lambda cls: cls.DEFAULT_PORT, type=int, metavar='PORT', help='Port to run server on [%(default)s]') num_threads = option(name='threads', default=10, type=int, metavar='N', help='Server Worker Threads [%(default)s]') def initTask(self): """Overridden to bind sockets, etc""" super(NBServerTask, self).initTask() self._stopped = False self.socket = TServerSocket(self.host, self.port) self.server = TNonblockingServer(self.processor, self.socket, threads=self.num_threads) self.server.prepare() self.bound_host, self.bound_port = \ self.server.socket.handle.getsockname() self.logger.info("%s Server Started on %s:%s", self.name, self.bound_host, self.bound_port) def stop(self): """Overridden to tell the thrift server to shutdown asynchronously""" self.server.stop() self.server.close() self._stopped = True def _runloop(self): """Overridden to execute TNonblockingServer's main loop""" while not self.server._stop: self.server.serve() while not self._stopped: time.sleep(0.1)
class NBServerTask(ThriftServerTask): """Spin up a thrift TNonblockingServer in a sparts worker thread""" DEFAULT_HOST = '0.0.0.0' DEFAULT_PORT = 0 OPT_PREFIX = 'thrift' bound_host = bound_port = None host = option(default=lambda cls: cls.DEFAULT_HOST, metavar='HOST', help='Address to bind server to [%(default)s]') port = option(default=lambda cls: cls.DEFAULT_PORT, type=int, metavar='PORT', help='Port to run server on [%(default)s]') num_threads = option(name='threads', default=10, type=int, metavar='N', help='Server Worker Threads [%(default)s]') def initTask(self): """Overridden to bind sockets, etc""" super(NBServerTask, self).initTask() self._stopped = False # Construct TServerSocket this way for compatibility with fbthrift self.socket = TServerSocket(port=self.port) self.socket.host = self.host self.server = TNonblockingServer(self.processor, self.socket, threads=self.num_threads) self.server.prepare() self.bound_addrs = [] for handle in self._get_socket_handles(self.server.socket): addrinfo = handle.getsockname() self.bound_host, self.bound_port = addrinfo[0:2] self.logger.info("%s Server Started on %s", self.name, self._fmt_hostport(self.bound_host, self.bound_port)) def _get_socket_handles(self, tsocket): """Helper to retrieve the socket objects for a given TServerSocket""" handle = getattr(tsocket, 'handle', None) if handle is not None: return [tsocket.handle] # Some TServerSocket implementations support multiple handles per # TServerSocket (e.g., to support binding v4 and v6 without # v4-mapped addresses return tsocket.handles.values() def _fmt_hostport(self, host, port): if ':' in host: return '[%s]:%d' % (host, port) else: return '%s:%d' % (host, port) def stop(self): """Overridden to tell the thrift server to shutdown asynchronously""" self.server.stop() self.server.close() self._stopped = True def _runloop(self): """Overridden to execute TNonblockingServer's main loop""" while not self.server._stop: self.server.serve() while not self._stopped: time.sleep(0.1)