Skip to content

Latest commit

 

History

History
260 lines (169 loc) · 7.07 KB

UPGRADE.rst

File metadata and controls

260 lines (169 loc) · 7.07 KB

Upgrade Guide

Migrating to a version of TChannel with breaking changes? This guide documents what broke and how to safely migrate to newer versions.

From 0.20 to 0.21

  • tchannel.thrift.register returns the original function as-is instead of the wrapped version. This allows writing unit tests that call the handler function directly.

    Previously, if you used the tchannel.thrift.register decorator to register a Thrift endpoint and then called that function directly from a test, it would return a Response object if the call succeeded or failed with an expected exception (defined in the Thrift IDL). For example,

    # service KeyValue {
    #   string getValue(1: string key)
    #      throws (1: ValidationError invalid)
    # }
    
    @tchannel.thrift.register(kv.KeyValue)
    def getValue(request):
        key = request.body.key
        if key == 'invalid':
            raise kv.ValidationError()
        result = # ...
        return result
    
    response = getValue(make_request(key='invalid'))
    if response.body.invalid:
        # ...
    else:
        result = response.body.success

    With 0.21, we have changed tchannel.thrift.register to return the unmodified function so that you can call it directly and it will behave as expected.

    @tchannel.thrift.register(kv.KeyValue)
    def getValue(request):
        # ...
    
    try:
        result = getValue(make_request(key='invalid'))
    except kv.ValidationError:
        # ...

From 0.19 to 0.20

  • No breaking changes.

From 0.18 to 0.19

  • No breaking changes.

From 0.17 to 0.18

  • request.headers in a JSON handler is no longer a JSON blob. Instead it is a dictionary mapping strings to strings. This matches the Thrift implementation. If your headers include richer types like lists or ints, you'll need to coordinate with your callers to no longer pass headers as JSON blobs. The same applies to JSON requsts; rich headers will now fail to serialize.

  • If you were accessing request_cls or response_cls directly from a service method in a module generated by tchannel.thrift.load, you can no longer do that. The request_cls and response_cls attributes are internal details of the implementation and have been changed to protected. You should only ever use the service method directly.

    Before:

    my_service.doSomething.request_cls(..)

    After:

    my_service.doSomething(..)

    Note that request_cls gives you just an object containing the method arguments. It does not include any of the other information needed to make the request. So if you were using it to make requests, it wouldn't have worked anyway.

From 0.16 to 0.17

  • No breaking changes.

From 0.15 to 0.16

  • tchannel.TChannel.register no longer mimicks tchannel.tornado.TChannel.register, instead it exposes the new server API like so:

    Before:

    from tchannel.tornado import TChannel
    
    tchannel = TChannel('my-service-name')
    
    @tchannel.register('endpoint', 'json')
    def endpoint(request, response, proxy):
        response.write({'resp': 'body'})

    After:

    from tchannel import TChannel
    
    tchannel = TChannel('my-service-name')
    
    @tchannel.json.register
    def endpoint(request):
        return {'resp': 'body'}
    
        # Or, if you need to return headers with your response:
        from tchannel import Response
        return Response({'resp': 'body'}, {'header': 'foo'})
  • TChannelSyncClient has been replaced with tchannel.sync.TChannel. This new synchronous client has been significantly re-worked to more closely match the asynchronous TChannel API. tchannel.sync.thrift.client_for has been removed and tchannel.thrift_request_builder should be used instead (tchannel.thrift.client_for still exists for backwards compatibility but is not recommended). This new API allows specifying headers, timeouts, and retry behavior with Thrift requests.

    Before:

    from tchannel.sync import TChannelSyncClient
    from tchannel.sync.thrift import client_for
    
    from generated.thrift.code import MyThriftService
    
    tchannel_thrift_client = client_for('foo', MyThriftService)
    
    tchannel = TChannelSyncClient(name='bar')
    
    future = tchannel_thrift_client.someMethod(...)
    
    result = future.result()

    After:

    from tchannel import thrift_request_builder
    from tchannel.sync import TChannel
    from tchannel.retry import CONNECTION_ERROR_AND_TIMEOUT
    
    from generated.thrift.code import MyThriftService
    
    tchannel_thrift_client = thrift_request_builder(
        service='foo',
        thrift_module=MyThriftService,
    )
    
    tchannel = TChannel(name='bar')
    
    future = tchannel.thrift(
        tchannel_thrift_client.someMethod(...)
        headers={'foo': 'bar'},
        retry_on=CONNECTION_ERROR_AND_TIMEOUT,
        timeout=1000,
    )
    
    result = future.result()
  • from tchannel.tornado import TChannel is deprecated.

  • Removed retry_delay option from tchannel.tornado.peer.PeerClientOperation.send method.

    Before: tchannel.tornado.TChannel.request.send(retry_delay=300)

    After: no more retry_delay in tchannel.tornado.TChannel.request.send()

  • If you were catching ProtocolError you will need to catch a more specific type, such as TimeoutError, BadRequestError, NetworkError, UnhealthyError, or UnexpectedError.

  • If you were catching AdvertiseError, it has been replaced by TimeoutError.

  • If you were catching BadRequest, it may have been masking checksum errors and fatal streaming errors. These are now raised as FatalProtocolError, but in practice should not need to be handled when interacting with a well-behaved TChannel implementation.

  • TChannelApplicationError was unused and removed.

  • Three error types have been introduced to simplify retry handling:

    • NotRetryableError (for requests should never be retried),
    • RetryableError (for requests that are always safe to retry), and
    • MaybeRetryableError (for requests that are safe to retry on idempotent endpoints).

From 0.14 to 0.15

  • No breaking changes.

From 0.13 to 0.14

  • No breaking changes.

From 0.12 to 0.13

  • No breaking changes.

From 0.11 to 0.12

  • Removed print_arg. Use request.get_body() instead.

From 0.10 to 0.11

  • Renamed tchannel.tornado.TChannel.advertise argument router to routers. Since this is a required arg and the first positional arg, only clients who are using as kwarg will break.

    Before: tchannel.advertise(router=['localhost:21300'])

    After: tchannel.advertise(routers=['localhost:21300'])