API Documentation

TChannel

class tchannel.TChannel(name, hostport=None, process_name=None, known_peers=None, trace=False)[source]

Make requests to TChannel services.

call(*args, **kwargs)[source]

Make low-level requests to TChannel services.

This method uses TChannel’s protocol terminology for param naming.

For high level requests with automatic serialization and semantic param names, use raw, json, and thrift methods instead.

Parameters:
  • scheme (string) – Name of the Arg Scheme to be sent as the Transport Header as; eg. ‘raw’, ‘json’, ‘thrift’ are all valid values.
  • service (string) – Name of the service that is being called. This is used internally to route requests through Hyperbahn, and for grouping of connection, and labelling stats. Note that when hostport is provided, requests are not routed through Hyperbahn.
  • arg1 (string) – Value for arg1 as specified by the TChannel protocol - this varies by Arg Scheme, but is typically used for endpoint name.
  • arg2 (string) – Value for arg2 as specified by the TChannel protocol - this varies by Arg Scheme, but is typically used for app-level headers.
  • arg3 (string) – Value for arg3 as specified by the TChannel protocol - this varies by Arg Scheme, but is typically used for the request body.
  • timeout (int) – How long to wait before raising a TimeoutError - this defaults to tchannel.glossary.DEFAULT_TIMEOUT.
  • retry_on (string) – What events to retry on - valid values can be found in tchannel.retry.
  • retry_limit (string) – How many times to retry before
  • hostport (string) – A ‘host:port’ value to use when making a request directly to a TChannel service, bypassing Hyperbahn.
class tchannel.schemes.RawArgScheme(tchannel)[source]

Semantic params and serialization for raw.

class tchannel.schemes.JsonArgScheme(tchannel)[source]

Semantic params and serialization for json.

class tchannel.schemes.ThriftArgScheme(tchannel)[source]

Semantic params and serialization for Thrift.

class tchannel.tornado.RequestDispatcher[source]

A synchronous RequestHandler that dispatches calls to different endpoints based on arg1.

Endpoints are registered using register or the route decorator.

handler = # ...

@handler.route('my_method')
def my_method(request, response, proxy):
    response.write('hello world')
static not_found(request, response, proxy)[source]

Default behavior for requests to unrecognized endpoints.

register(rule, handler, broker=None)[source]

Register a new endpoint with the given name.

@dispatcher.register('is_healthy')
def check_health(request, response, proxy):
    # ...
Parameters:
  • rule

    Name of the endpoint. Incoming Call Requests must have this as arg1 to dispatch to this handler.

    If RequestHandler.FALLBACK is specified as a rule, the given handler will be used as the ‘fallback’ handler when requests don’t match any registered rules.

  • handler – A function that gets called with Request, Response, and the proxy.
  • broker

    Broker injects customized serializer and deserializer into request/response object.

    broker==None means it registers as raw handle. It deals with raw buffer in the request/response.

route(rule, helper=None)[source]

See register for documentation.

class tchannel.tornado.Request(id=None, flags=0, ttl=1000, tracing=None, service=None, headers=None, checksum=None, argstreams=None, scheme=None, endpoint=None)[source]

Represents an incoming request to an endpoint.

Request class is used to represent the CallRequestMessage at User’s level. This is going to hide the protocol level message information.

get_body(*args, **kwargs)[source]

Get the body value from the resquest.

Returns:a future contains the deserialized value of body
get_body_s()[source]

Get the raw stream of body.

Returns:the argstream of body
get_header(*args, **kwargs)[source]

Get the header value from the request.

Returns:a future contains the deserialized value of header
get_header_s()[source]

Get the raw stream of header.

Returns:the argstream of header
should_retry_on_error(error)[source]

rules for retry

Parameters:error – ProtocolException that returns from Server
class tchannel.tornado.Response(connection=None, id=None, flags=None, code=None, tracing=None, headers=None, checksum=None, argstreams=None, scheme=None)[source]

An outgoing response.

Response class is used to represent the CallResponseMessage at User’s level. This is going to hide the protocol level message information.

flush()[source]

Flush the response buffer.

No more write or set operations is allowed after flush call.

get_body(*args, **kwargs)[source]

Get the body value from the response.

Returns:a future contains the deserialized value of body
get_body_s()[source]

Get the raw stream of body.

Returns:the argstream of body
get_header(*args, **kwargs)[source]

Get the header value from the response.

Returns:a future contains the deserialized value of header
get_header_s()[source]

Get the raw stream of header.

Returns:the argstream of header
set_body_s(stream)[source]

Set customized body stream.

Note: the body stream can only be changed before the stream is consumed.

Parameters:stream – InMemStream/PipeStream for body
Raises TChannelError:
 Raise TChannelError if the stream is being sent when you try to change the stream.
set_header_s(stream)[source]

Set customized header stream.

Note: the header stream can only be changed before the stream is consumed.

Parameters:stream – InMemStream/PipeStream for header
Raises TChannelError:
 Raise TChannelError if the stream is being sent when you try to change the stream.
write_body(chunk)[source]

Write to header.

Note: whenever write_body is called, the header stream will be closed. write_header method is unavailable.

Parameters:chunk – content to write to body
Raises TChannelError:
 Raise TChannelError if the response’s flush() has been called
write_header(chunk)[source]

Write to header.

Note: the header stream is only available to write before write body.

Parameters:chunk – content to write to header
Raises TChannelError:
 Raise TChannelError if the response’s flush() has been called

Exceptions

exception tchannel.errors.AdvertiseError[source]

Represent advertise failure exception

exception tchannel.errors.AlreadyListeningError[source]

Represents exception from attempting to listen multiple times.

exception tchannel.errors.InvalidChecksumError[source]

Represent invalid checksum type in the message

exception tchannel.errors.InvalidEndpointError[source]

Represent an message containing invalid endpoint.

exception tchannel.errors.InvalidErrorCodeError(code)[source]

Represent Invalid Error Code exception

exception tchannel.errors.InvalidMessageError[source]

Represent an invalid message.

exception tchannel.errors.NoAvailablePeerError[source]

Represents a failure to find any peers for a request.

exception tchannel.errors.OneWayNotSupportedError[source]

Raised when oneway Thrift procedure is called.

exception tchannel.errors.ProtocolError(code, description, id=None, tracing=None)[source]

Represent a protocol-level exception

exception tchannel.errors.ReadError[source]

Raised when there is an error while reading input.

exception tchannel.errors.StreamingError[source]

Represent Streaming Message Exception

exception tchannel.errors.TChannelApplicationError(code, args)[source]

The remote application returned an exception.

This is not a protocol error. This means a response was received with the code flag set to fail.

exception tchannel.errors.TChannelError[source]

Represent a TChannel-generated exception.

exception tchannel.errors.ValueExpectedError[source]

Raised when a non-void Thrift response contains no value.

Thrift

tchannel.thrift.client.client_for(service, service_module, thrift_service_name=None)[source]

Build a client class for the given Thrift service.

The generated class accepts a TChannel and an optional hostport as initialization arguments.

Given CommentService defined in comment.thrift and registered with Hyperbahn under the name “comment”, here’s how this may be used:

from comment import CommentService

CommentServiceClient = client_for("comment", CommentService)

@gen.coroutine
def post_comment(articleId, msg, hostport=None):
    client = CommentServiceClient(tchannel, hostport)
    yield client.postComment(articleId, CommentService.Comment(msg))
Parameters:
  • service – Name of the Hyperbahn service being called. This is the name with which the service registered with Hyperbahn.
  • service_module – The Thrift-generated module for that service. This usually has the same name as defined for the service in the IDL.
  • thrift_service_name – If the Thrift service has a different name than its module, use this parameter to specify it.
Returns:

An object with the same interface as the service that uses the given TChannel to call the service.

tchannel.thrift.client.generate_method(service_module, service_name, method_name)[source]

Generate a method for the given Thrift service.

Parameters:
  • service_module – Thrift-generated service module
  • service_name – Name of the Thrift service
  • method_name – Method being called

Synchronous Client

class tchannel.sync.client.Response(header, body)
body

Alias for field number 1

header

Alias for field number 0

class tchannel.sync.client.SyncClientOperation(operation, threadloop)[source]

Allows making client operation requests synchronously.

This object acts like tchannel.TChannelClientOperation, but instead uses a threadloop to make the request synchronously.

send(arg1, arg2, arg3)[source]

Send the given triple over the wire.

Parameters:
  • arg1 – String containing the contents of arg1. If None, an empty string is used.
  • arg2 – String containing the contents of arg2. If None, an empty string is used.
  • arg3 – String containing the contents of arg3. If None, an empty string is used.
Return concurrent.futures.Future:
 

Future response from the peer.

class tchannel.sync.client.TChannelSyncClient(name, process_name=None, known_peers=None, trace=False)[source]

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.

client = TChannelSyncClient()
response = client.request(
    hostport='localhost:4040',
    service='HelloService',
).send(
    'hello', None, json.dumps({"name": "World"})
)
advertise(routers, name=None, timeout=None)[source]

Advertise with Hyperbahn.

Parameters:
  • routers – list of hyperbahn addresses to advertise to.
  • name – service name to advertise with.
  • timeout – backoff period for failed requests.
Returns:

first advertise result.

Raises AdvertiseError:
 

when unable to begin advertising.

request(*args, **kwargs)[source]

Initiate a new request to a peer.

Parameters:
  • hostport – If specified, requests will be sent to the specific host. Otherwise, a known peer will be picked at random.
  • service – Name of the service being called. Defaults to an empty string.
  • 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.

tchannel.sync.thrift.client_for(service, service_module, thrift_service_name=None)[source]

Build a synchronous client class for the given Thrift service.

The generated class accepts a TChannelSyncClient and an optional hostport as initialization arguments.

Given CommentService defined in comment.thrift and registered with Hyperbahn under the name “comment”, here’s how this might be used:

from tchannel.sync import TChannelSyncClient
from tchannel.sync.thrift import client_for

from comment import CommentService

CommentServiceClient = client_for('comment', CommentService)

tchannel_sync = TChannelSyncClient('my-service')
comment_client = CommentServiceClient(tchannel_sync)

future = comment_client.postComment(
    articleId,
    CommentService.Comment("hi")
)
result = future.result()
Parameters:
  • service – Name of the Hyperbahn service being called.
  • service_module – The Thrift-generated module for that service. This usually has the same name as definied for the service in the IDL.
  • thrift_service_name – If the Thrift service has a different name than its module, use this parameter to specify it.
Returns:

An Thrift-like class, ready to be instantiated and used with TChannelSyncClient.

tchannel.sync.thrift.generate_method(method_name)[source]

Generate a method for a given Thrift service.

Uses the provided TChannelSyncClient’s threadloop in order to convert RPC calls to concurrent.futures

Parameters:method_name – Method being called.
Returns:A method that invokes the RPC using TChannelSyncClient

Testing

VCR

tchannel.testing.vcr provides VCR-like functionality for TChannel. Its API is heavily inspired by the vcrpy library.

This allows recording TChannel requests and their responses into YAML files during integration tests and replaying those recorded responses when the tests are run next time.

The simplest way to use this is with the use_cassette() function.

tchannel.testing.vcr.use_cassette(path, record_mode=None, inject=False)[source]

Use or create a cassette to record/replay TChannel requests.

This may be used as a context manager or a decorator.

from tchannel.testing import vcr

@pytest.mark.gen_test
@vcr.use_cassette('tests/data/foo.yaml')
def test_foo():
    channel = TChannel('test-client')
    service_client = MyServiceClient(channel)

    yield service_client.myMethod()


def test_bar():
    with vcr.use_cassette('tests/data/bar.yaml', record_mode='none'):
        # ...

Note that when used as a decorator on a coroutine, the use_cassette decorator must be applied BEFORE gen.coroutine or pytest.mark.gen_test.

Parameters:
  • path – Path to the cassette. If the cassette did not already exist, it will be created. If it existed, its contents will be replayed (depending on the record mode).
  • record_mode – The record mode dictates whether a cassette is allowed to record or replay interactions. This may be a string specifying the record mode name or an element from the tchannel.testing.vcr.RecordMode object. This parameter defaults to tchannel.testing.vcr.RecordMode.ONCE. See tchannel.testing.vcr.RecordMode for details on supported record modes and how to use them.
  • inject – If True, when use_cassette is used as a decorator, the cassette object will be injected into the function call as the first argument. Defaults to False.

Configuration

Record Modes
class tchannel.testing.vcr.RecordMode[source]

Record modes dictate how a cassette behaves when interactions are replayed or recorded. The following record modes are supported.

ONCE = 'once'

If the YAML file did not exist, record new interactions and save them. If the YAML file already existed, replay existing interactions but disallow any new interactions. This is the default and usually what you want.

NEW_EPISODES = 'new_episodes'

Replay existing interactions and allow recording new ones. This is usually undesirable since it reduces predictability in tests.

NONE = 'none'

Replay existing interactions and disallow any new interactions. This is a good choice for tests whose behavior is unlikely to change in the near future. It ensures that those tests don’t accidentally start making new requests.

ALL = 'all'

Do not replay anything and record all new interactions. Forget all existing interactions. This may be used to record everything anew.