Expand description

TChannel is a network multiplexing and framing RPC protocol created by Uber (protocol specs).

Overview

Features of TChannel protocol implemented so far:

  • A request/response model,
  • Multiplexing multiple requests across the same TCP socket,
  • Out-of-order responses,
  • Streaming requests and responses,
  • Checksums of frame args (only None),
  • Transport of arbitrary payloads:
    • Thrift
    • SThrift (streaming Thrift)
    • JSON
    • HTTP
    • Raw
  • Routing mesh
  • Tracing

Other TODOs:

  • Request response TTL
  • Cancel request
  • Claim requests
  • Use Tower?
  • Implement Serde Serialize/Deserialize for Message types
  • Convert Thrift related Makefile to build.rs when implementing Thrift payloads
  • Proper tests (right now only few happy paths)
  • Make request handlers generic (no associated types)

The goal of the project is to provide a similar API to Java TChannel implementation which is why both connection pools and server task handler are hidden from user.

Disclaimer

It is an unofficial implementation of TChannel protocol. The project is used to learn Rust and it still has some missing features, so it will not go out of 0.0.x before implementing them and a proper testing. Future 0.0.x releases may include API breaking changes.

Examples

use tchannel_rs::{Config, TChannel, TResult};
use tchannel_rs::handler::{HandlerResult, RequestHandler};
use tchannel_rs::messages::{MessageChannel, RawMessage};

#[tokio::main]
async fn main() -> TResult<()> {
    // Server
    let mut tserver = TChannel::new(Config::default())?;
    let subchannel = tserver.subchannel("service").await?;
    subchannel.register("endpoint", Handler {}).await?;
    tserver.start_server()?;

    // Client
    let tclient = TChannel::new(Config::default())?;
    let subchannel = tclient.subchannel("service").await?;
    let request = RawMessage::new("endpoint".into(), "header".into(), "req body".into());
    let response = subchannel.send(request, "127.0.0.1:8888").await.unwrap();

    // Server shutdown
    tserver.shutdown_server();

    assert_eq!("header", response.header());
    assert_eq!("res body".as_bytes(), response.body().as_ref());
    Ok(())
}

#[derive(Debug)]
struct Handler {}
impl RequestHandler for Handler {
    type REQ = RawMessage;
    type RES = RawMessage;
    fn handle(&mut self, request: Self::REQ) -> HandlerResult<Self::RES> {
        Ok(RawMessage::new(request.endpoint().clone(), request.header().clone(), "res body".into()))
    }
}

Modules

TChannel errors.

Handlers registered in SubChannel and called by server started from TChannel.

Messages send from SubChannel and handled by RequestHandler (RequestHandlerAsync)

Structs

TChannel config

Builder for Config.

TChannel protocol subchannel.

TChannel protocol. Keeps started server handle and created SubChannels.

Type Definitions

TChannel general result.