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
, andthrift
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 totchannel.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.
- scheme (string) – Name of the Arg Scheme to be sent as the Transport Header
-
-
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 theroute
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 theproxy
. - 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.
- rule –
-
static
-
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
-
-
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_header
(*args, **kwargs)[source]¶ Get the header value from the response.
Returns: a future contains the deserialized value 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.
-
Exceptions¶
-
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.
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
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 incomment.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.
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 incomment.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 BEFOREgen.coroutine
orpytest.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 totchannel.testing.vcr.RecordMode.ONCE
. Seetchannel.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.
-