containerd / ttrpc-rust

Rust implementation of ttrpc (GRPC for low-memory environments)
Apache License 2.0
195 stars 45 forks source link

Codegen with `Arc<dyn ..>` instead of `Arc<Box<..>>` #234

Closed Xynnn007 closed 4 days ago

Xynnn007 commented 1 month ago

Hi, I am using ttrpc for some time. One thing confused me is that with ttrpc's Codegen, we would generate a .._ttrpc.rs where a XXXMethod would have a service member with type Arc<Box<dyn ...>> rather than Arc<dyn ...>.

I wonder if we could convert Arc<Box<dyn ...>> to Arc<dyn ...>?

The reason comes from some ttrpc server implementation.

We are using a proto with more-than-one Service, e.g.

service A {
    rpc funcA(ARequest) returns (AResponse) {};
}

service B {
    rpc funcB(BResquest) returns (BResponse) {};
}

We want that a same object would serve the two APIs, thus we have

// Server impls A and B
let server = Server::new();
let server = Arc::new(Box::new(server as _));

let a = create_a_service(server.clone());

// compiler errors because we cannot convert Arc<Box<T>> to both Arc<Box<dyn A>> and Arc<Box<dyn B>>
let b = create_a_service(server);

So what we can do is only to create two Servers to create different services, which means double the memory consumption.

If the ttrpc CodeGen returns type Arc<dyn T>, we can facilitate by

let server = Arc::new(Server::new());

let a = create_a_service(server.clone() as _);
let b = create_b_service(server as _);

let mut server = TtrpcServer::new()
        .bind(&socket)
        .unwrap()
        .register_service(a)
        .register_service(b);

where the as _ would help the compiler convert Arc<Server> to Arc<dyn A> and Arc<dyn B>.