コード例 #1
0
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
コード例 #2
0
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
コード例 #3
0
def test_ioloop_is_not_already_running():
    threadloop = ThreadLoop()
    threadloop.start()

    @gen.coroutine
    def f():
        yield threadloop.submit(gen.sleep, 0.1)

    ioloop.IOLoop.current().run_sync(f)
コード例 #4
0
def test_block_until_thread_is_ready():

    threadloop = ThreadLoop()

    assert not threadloop.is_ready()

    threadloop.start()

    assert threadloop.is_ready()
コード例 #5
0
def test_ioloop_is_not_already_running():
    threadloop = ThreadLoop()
    threadloop.start()

    @gen.coroutine
    def f():
        yield threadloop.submit(gen.sleep, 0.1)

    ioloop.IOLoop.current().run_sync(f)
コード例 #6
0
def test_block_until_thread_is_ready():

    threadloop = ThreadLoop()

    assert not threadloop.is_ready()

    threadloop.start()

    assert threadloop.is_ready()
コード例 #7
0
ファイル: client.py プロジェクト: pengzhai/tchannel
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,
            hostport=glossary.EPHEMERAL_HOSTPORT,
            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
コード例 #8
0
class LocalAgentSender(TBufferedTransport):
    """
    LocalAgentSender implements everything necessary to communicate with
    local jaeger-agent. This class is designed to work in tornado and
    non-tornado environments. If in torndado, pass in the ioloop, if not
    then LocalAgentSender will create one for itself.

    NOTE: LocalAgentSender derives from TBufferedTransport. This will buffer
    up all written data until flush() is called. Flush gets called at the
    end of the batch span submission call.
    """
    def __init__(self,
                 host,
                 sampling_port,
                 reporting_port,
                 io_loop=None,
                 throttling_port=None):
        # IOLoop
        self._thread_loop = None
        self.io_loop = io_loop or self._create_new_thread_loop()

        # HTTP sampling
        self.local_agent_http = LocalAgentHTTP(host, sampling_port)

        # HTTP throttling
        if throttling_port:
            self.throttling_http = LocalAgentHTTP(host, throttling_port)

        # UDP reporting - this will only get written to after our flush() call.
        # We are buffering things up because we are a TBufferedTransport.
        udp = TUDPTransport(host, reporting_port)
        TBufferedTransport.__init__(self, udp)

    def _create_new_thread_loop(self):
        """
        Create a daemonized thread that will run Tornado IOLoop.
        :return: the IOLoop backed by the new thread.
        """
        self._thread_loop = ThreadLoop()
        if not self._thread_loop.is_ready():
            self._thread_loop.start()
        return self._thread_loop._io_loop

    def readFrame(self):
        """Empty read frame that is never ready"""
        return Future()

    # Pass-through for HTTP sampling strategies request.
    def request_sampling_strategy(self, *args, **kwargs):
        return self.local_agent_http.request_sampling_strategy(*args, **kwargs)

    # Pass-through for HTTP throttling credit request.
    def request_throttling_credits(self, *args, **kwargs):
        return self.throttling_http.request_throttling_credits(*args, **kwargs)
コード例 #9
0
class Sender(object):
    def __init__(self, host, port, io_loop=None):
        self.host = host
        self.port = port
        self.io_loop = io_loop or self._create_new_thread_loop()

    def send(self, batch):
        raise NotImplementedError(
            'This method should be implemented by subclasses')

    def _create_new_thread_loop(self):
        """
        Create a daemonized thread that will run Tornado IOLoop.
        :return: the IOLoop backed by the new thread.
        """
        self._thread_loop = ThreadLoop()
        if not self._thread_loop.is_ready():
            self._thread_loop.start()
        return self._thread_loop._io_loop
コード例 #10
0
class LocalAgentSender(TBufferedTransport):
    """
    LocalAgentSender implements a everything necessary to communicate with local jaeger-agent. This
    class is designed to work in tornado and non-tornado environments. If in torndado, pass in
    the ioloop, if not then LocalAgentSender will create one for itself.

    NOTE: LocalAgentSender derives from TBufferedTransport. This will buffer up all written
    data until flush() is called. Flush gets called at the end of the batch span submission
    call.
    """

    def __init__(self, host, sampling_port, reporting_port, ioloop=None):
        # ioloop
        if ioloop is None:
            self.create_new_threadloop()
        else:
            self.io_loop = ioloop

        # http sampling
        self.local_agent_http = LocalAgentHTTP(host, sampling_port)

        # udp reporting - this will only get written to after our flush() call.
        # We are buffering things up because we are a TBufferedTransport.
        udp = TUDPTransport(host, reporting_port)
        TBufferedTransport.__init__(self, udp)

    def create_new_threadloop(self):
        self._threadloop = ThreadLoop()
        if not self._threadloop.is_ready():
            self._threadloop.start()
        self.io_loop = ioloop_util.get_io_loop(self)

    def readFrame(self):
        """Empty read frame that is never ready"""
        return Future()

    # Passthroughs for the http
    def request_sampling_strategy(self, service_name, timeout):
        return self.local_agent_http.request_sampling_strategy(service_name, timeout)
コード例 #11
0
ファイル: client.py プロジェクト: Willyham/tchannel-python
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
コード例 #12
0
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