Giter VIP home page Giter VIP logo

tonic-rpc's Introduction

tonic-rpc is a macro that generates the traits and stubs used by tonic from Rust definitions instead of proto files.

This means that you can get all the benefits of tonic while using regular Rust types and without needing to use proto files or build scripts. Of course, this comes at the sacrifice of interoperability.

Crates.io Documentation Build Status License Downloads

Alternatives

tarpc is an excellent RPC library that also defines services as a Rust trait.

Required dependencies

tonic = "0.8.3"
tonic-rpc = { version = "0.2.1", features = [ <enabled-codecs> ] }

Example

Instead of defining a proto file, define a service as a trait:

#[tonic_rpc::tonic_rpc(json)]
trait Increment {
    fn increment(arg: i32) -> i32;
}

The attribute #[tonic_rpc(json)] indicates that this service will serialize the requests and responses using json. Other encodings are available. The arguments and return values for each function must implement serde::Serialize and serde::Deserialize.

The service can be implemented by defining an impl:

struct State;

#[tonic::async_trait]
impl increment_server::Increment for State {
    async fn increment(
        &self,
        request: tonic::Request<i32>,
    ) -> Result<tonic::Response<i32>, tonic::Status> {
        Ok(tonic::Response::new(request.into_inner() + 1))
    }
}

And a server and client can be run:

async fn run_client_server() {
    let mut listener = tokio::net::TcpListener::bind("[::1]:0").await.unwrap();
    let addr = listener.local_addr().unwrap();
    tokio::spawn(async move {
        tonic::transport::Server::builder()
            .add_service(increment_server::IncrementServer::new(State))
            .serve_with_incoming(tokio_stream::wrappers::TcpListenerStream::new(listener))
            .await
    });
    let mut client = increment_client::IncrementClient::connect(format!("http://{}", addr))
        .await
        .unwrap();
    let response = client.increment(32).await.unwrap().into_inner();
    assert_eq!(33, response);
}

The full example is available here. Further examples are available in the tests folder.

Encodings

Multiple codecs are available for serializing the RPC request/response types. Each codec is enabled by a feature flag. At least one of these features must be enabled.

E.g. To use the encode using cbor, use the attribute

#[tonic_rpc::tonic_rpc(cbor)]

and include

tonic-rpc = { version = "0.2.1", features = [ "cbor" ]}

in Cargo.toml.

Streaming

Streaming can be added on the client or server side by adding the attributes #[client_streaming] or #[server_streaming] to a function in the service trait. These behave the same as if the stream keyword were added to a proto definition.

Examples that use streaming can be found in the tests folder.

Request/Response types

The traits and functions generated by tonic-rpc will be transformations of the methods defined in the tonic_rpc trait that have been modified to add handling of gRPC request/response types, async, and streaming.

This is a summary of how signatures are transformed:

Arguments

fn f(x: X, y:Y) -> ..

becomes

async fn f(&self, arg: tonic::Request<(X,Y)>) -> ..

Return value

fn f(..) -> Z

becomes

async fn f(..) -> Result<tonic::Response<Z>, tonic::Status>

Streaming arguments

#[client_streaming]
fn f(x:X) -> ..

becomes

async fn f(&self, arg: tonic::Request<tonic::Streaming<X>>) -> ..

Streaming return value

#[server_streaming]
fn f(..) -> Z

becomes

type FStream: Stream<Item = Result<Z, tonic::Status>>;

async fn f(..) -> Result::<tonic::Response<Self::FStream>, tonic::Status>

tonic-rpc's People

Contributors

adamrk avatar boydjohnson avatar snowkat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

tonic-rpc's Issues

Is it possible to generate schema?

I am currently new to grpc. Wondering if you could generate client bindings to RPC server using a different language like typescript for example?

Possible to use with simd-json?

Is it possible to use tonic-rpc with simd-json (with the serde_impl flag)? Does this require implementing a new codec similar to the existing JSON version or is there a way to plug in an alternative implementation?

#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
pub struct JsonSerdeCodec;

#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
impl SerdeCodec for JsonSerdeCodec {
fn write<T, W>(item: T, w: W) -> Result<(), Status>
where
T: Serialize,
W: Write,
{
serde_json::to_writer(w, &item)
.map_err(|serde_err| Status::internal(format!("Error serializing {}", serde_err)))
}
fn read<T, R>(r: R) -> Result<T, Status>
where
T: for<'de> Deserialize<'de>,
R: Read,
{
serde_json::from_reader(r)
.map_err(|serde_err| Status::internal(format!("Error deserializing {}", serde_err)))
}
}

#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
pub type JsonCodec<T, U> = Codec<JsonSerdeCodec, T, U>;

Crate fails to build with tonic_build 0.8.4

It appears that tonic changed the interface of the tonic_build::client::generate API, which is causing tonic-rpc-macro to no longer build.

The breaking change landed in this commit: hyperium/tonic@1f5bc9b

   Compiling tonic-rpc-macro v0.2.0
error[E0061]: this function takes 6 arguments but 5 arguments were supplied
   --> /Users/ian/.cargo/registry/src/github.com-1ecc6299db9ec823/tonic-rpc-macro-0.2.0/src/lib.rs:251:18
    |
251 |     let client = tonic_build::client::generate(&service, false, "", false, &Attributes::default());
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                             ---------------------- an argument of type `bool` is missing
    |
note: function defined here
   --> /Users/ian/.cargo/registry/src/github.com-1ecc6299db9ec823/tonic-build-0.8.4/src/client.rs:13:8
    |
13  | pub fn generate<T: Service>(
    |        ^^^^^^^^
help: provide the argument
    |
251 |     let client = tonic_build::client::generate(&service, false, "", false, /* bool */, &Attributes::default());
    |                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

error: aborting due to previous error

Dead or alive

Hello. You have a very interesting project. Will you continue to support it, update the version?

Let's meet

Hey Adam,
I’m the founder of a novel L1 blockchain project called Repyh. We are wrapping up the pre-seed round, and are currently hiring for the very important first few positions. I quite like your background doing pure maths and HFT, as well as doing blockchain stuff at Dfinity.

Feel free to check out the whitepaper: https://docsend.com/view/99fssq7k59spnz37
The tl;dr is that Repyh will be immensely scalable while still possible to verify on a phone, it introduces a novel economic model, and it will hopefully serve as economic and financial infrastructure for large parts of the world.

Let me know if you’re interested in chatting,
Ole

A sorely needed project!

@adamrk thanks for all of the work on this project! IMHO, this is sorely needed, as there seem to be lots of cases where gRPC networking is great in terms of functionality and performance, but protobuf is just ... not so great.

I am currently hacking on a project which is using standard grpc/protobuf, but I would like to cut things over to use this project along with something like NoProto or Flexbuf.

Any plans for taking this project to [email protected] & tokio@1? That is actually not a super pressing need for me at the moment, but will like be within the next few months. I see #14 is in flight! Awesome.

Lastly, any recommendations on getting started with NoProto or Flexbuf interop with this crate?

Ditching unneeded features may help running tonic-rpc on wasm32 arch

Hi, I was wondering if tonic and tonic-build dependencies could be imported with default-features = false. This way, the project could also build on wasm32-unknown-unknown target (tonic wouldn't bring in tokio "full", tonic-build wouldn't bring in prost-build, which in turn uses which package, unavailable on wasm32 arch).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.