Hi, everyone.
I'm currently implementing gRPC in rust.
Currently it does only basic things: synchronous client and synchronous server, and no streaming.
I could continue developing synchronous version of client, but I think it would be wise to implement asynchronous client and server, and make synchronous versions thin wrappers around asynchronous versions.
I have experience in implementing asynchronous things in C++ and Java, but I practically never written any asynchronous in Rust.
So. I basically have two questions: what an interface of gRPC should be, and how should it be implemented.
I've looked at sources of several libraries in rust, and seems like my choice is futures-rs for the API, mio+futures-mio for the event loop and solicit for the implementation of HTTP/2 protocol.
So, given service defition
service FileService {
rpc listFiles(ListFilesRequest) returns ListFilesResponse {};
rpc uploadFile(stream UploadFileRequest) returns UploadFileResponse {};
rpc downloadFile(stream DownloadFileRequest) returns stream DownloadFileResponse {};
}
rust-grpc compiler should generate a trait:
type GrpcFuture<T> = Box<Future<T, GrpcError>>;
type GrpcStream<T> = Box<Stream<T, GrpcError>>;
trait FileServiceAsync {
GrpcFuture<ListFilesResponse> listFiles(&self, req: ListFilesRequest);
GrpcFuture<UploadFileResponse> uploadFile(&self,
req: GrpcStream<UploadFileRequest>);
GrpcStream<DownloadFileResponse> downloadFile(&self,
req: DownloadFileRequest);
}
class FileServiceAsyncClient {
... generated client
}
This trait would be used by both client and server. rust-gprc compiler will generate stub FileServiceAsyncClient
, and user should imeplement this trait for the server.
So, given this interface for generated code, and choice of libraries, singlethread event loop implementation is pretty much straighforward (although wordy).
BTW, I've looked at C++ version of gRPC, it looks like it was designed by aliens for predators (whereas Go and Java asynchronous interfaces are simple and clear). I think simpler and easier to use interface is possible in low-level language. Or I simply miss something important.
So, that's it. Any advice, before I started writing a lot of code, is welcome.