def test_start_must_be_called_before_submit(): threadloop = ThreadLoop() @gen.coroutine def coroutine(): raise gen.Return("Hello World") with pytest.raises(ThreadNotStartedError): threadloop.submit(coroutine)
def test_main_io_loop_is_not_changed(): threadloop = ThreadLoop() threadloop.start() # The ThreadLoop's IOLoop should not be the 'current' IOLoop in the main # thread. tl_loop = threadloop.submit(ioloop.IOLoop.current).result() assert ioloop.IOLoop.current() is not tl_loop
def test_use_existing_ioloop(): io_loop = ioloop.IOLoop.current() threadloop = ThreadLoop(io_loop) assert threadloop._io_loop is io_loop @gen.coroutine def coroutine(): raise gen.Return("Hello World") with threadloop: future = threadloop.submit(coroutine) assert future.result() == "Hello World"
class TChannelSyncClient(object): """Make synchronous TChannel requests. This client does not support incoming connections or requests- this is a uni-directional client only. The client is implemented on top of the Tornado-based implementation and starts and stops IOLoops on-demand. .. code-block:: python client = TChannelSyncClient() response = client.request( hostport='localhost:4040', service='HelloService', ).send( 'hello', None, json.dumps({"name": "World"}) ) """ def __init__(self, name, process_name=None, known_peers=None, trace=False): """Initialize a new TChannelClient. :param process_name: Name of the calling process. Used for logging purposes only. """ self._async_client = async.TChannel(name, process_name=process_name, known_peers=known_peers, trace=trace) self._threadloop = ThreadLoop() self._threadloop.start() def request(self, *args, **kwargs): """Initiate a new request to a peer. :param hostport: If specified, requests will be sent to the specific host. Otherwise, a known peer will be picked at random. :param service: Name of the service being called. Defaults to an empty string. :param service_threshold: If ``hostport`` was not specified, this specifies the score threshold at or below which peers will be ignored. :returns SyncClientOperation: An object with a ``send(arg1, arg2, arg3)`` operation. """ operation = self._async_client.request(*args, **kwargs) operation = SyncClientOperation(operation, self._threadloop) return operation def advertise(self, routers, name=None, timeout=None): """Advertise with Hyperbahn. :param routers: list of hyperbahn addresses to advertise to. :param name: service name to advertise with. :param timeout: backoff period for failed requests. :returns: first advertise result. :raises AdvertiseError: when unable to begin advertising. """ @gen.coroutine def make_request(): response = yield self._async_client.advertise(routers=routers, name=name, timeout=timeout) header = yield response.get_header() body = yield response.get_body() result = Response(header, body) raise gen.Return(result) future = self._threadloop.submit(make_request) # we're going to wait 1s longer than advertises # timeout mechanism, so it has a chance to timeout wait_until = timeout or FIRST_ADVERTISE_TIME wait_until += 1 # block for advertise's first response, # using wait_until as a fallback timeout mechanism try: result = future.result(wait_until) except TimeoutError: raise AdvertiseError("Failed to register with Hyperbahn.") return result
class TChannelSyncClient(object): """Make synchronous TChannel requests. This client does not support incoming connections or requests- this is a uni-directional client only. The client is implemented on top of the Tornado-based implementation and starts and stops IOLoops on-demand. .. code-block:: python client = TChannelSyncClient() response = client.request( hostport='localhost:4040', service='HelloService', ).send( 'hello', None, json.dumps({"name": "World"}) ) """ def __init__(self, name, process_name=None, known_peers=None, trace=False): """Initialize a new TChannelClient. :param process_name: Name of the calling process. Used for logging purposes only. """ self._async_client = async .TChannel(name, process_name=process_name, known_peers=known_peers, trace=trace) self._threadloop = ThreadLoop() self._threadloop.start() def request(self, *args, **kwargs): """Initiate a new request to a peer. :param hostport: If specified, requests will be sent to the specific host. Otherwise, a known peer will be picked at random. :param service: Name of the service being called. Defaults to an empty string. :param service_threshold: If ``hostport`` was not specified, this specifies the score threshold at or below which peers will be ignored. :returns SyncClientOperation: An object with a ``send(arg1, arg2, arg3)`` operation. """ operation = self._async_client.request(*args, **kwargs) operation = SyncClientOperation(operation, self._threadloop) return operation def advertise(self, routers, name=None, timeout=None): """Advertise with Hyperbahn. :param routers: list of hyperbahn addresses to advertise to. :param name: service name to advertise with. :param timeout: backoff period for failed requests. :returns: first advertise result. :raises AdvertiseError: when unable to begin advertising. """ @gen.coroutine def make_request(): response = yield self._async_client.advertise( routers=routers, name=name, timeout=timeout, ) header = yield response.get_header() body = yield response.get_body() result = Response(header, body) raise gen.Return(result) future = self._threadloop.submit(make_request) # we're going to wait 1s longer than advertises # timeout mechanism, so it has a chance to timeout wait_until = timeout or FIRST_ADVERTISE_TIME wait_until += 1 # block for advertise's first response, # using wait_until as a fallback timeout mechanism try: result = future.result(wait_until) except TimeoutError: raise AdvertiseError("Failed to register with Hyperbahn.") return result