| Crates.io | comprehensive_grpc |
| lib.rs | comprehensive_grpc |
| version | 0.7.1 |
| created_at | 2024-10-22 23:12:24.138041+00 |
| updated_at | 2025-07-27 20:53:25.832778+00 |
| description | A harness for creating consistently-shaped servers will less boilerplate |
| homepage | https://github.com/vandry/comprehensive |
| repository | https://github.com/vandry/comprehensive.git |
| max_upload_size | |
| id | 1419431 |
| size | 199,666 |
[comprehensive] Resource types for gRPC client and server.
This crate provides Resource types for use in a [comprehensive]
Assembly. To use it, build an Assembly and include resources
from this crate in the dependency graph.
Define a struct containing a [tonic] client wrapped around a channel
and derive [GrpcClient] on it. This will become a
[comprehensive::v1::Resource] that can be depended upon. Call .client()
to get a (cheap) clone of the gRPC client.
use comprehensive_grpc::GrpcClient;
use comprehensive_grpc::client::Channel;
#[derive(GrpcClient)]
struct MyClientResource(
pb::test_client::TestClient<Channel>,
);
struct OtherResourceThatConsumesClient {
the_client: std::sync::Arc<MyClientResource>,
}
impl OtherResourceThatConsumesClient {
async fn something(&self) {
let mut tonic_client = self.the_client.client();
println!("{:?}", tonic_client.greet(()).await);
}
}
Derive resources that conjure the server and install themselves in it:
Any Resource that implements [GrpcService] and exports itself as a
trait resource for dyn GrpcService will be picked up automatically
by the server and served.
The #[export_grpc] attribute argument to the [comprehensive::v1::resource]
macro is a shortcut for #[export(dyn GrpcService)] and also
implementing the [GrpcService] trait.
use comprehensive::{NoArgs, NoDependencies, ResourceDependencies};
use comprehensive::v1::{AssemblyRuntime, Resource, resource};
use comprehensive_grpc::GrpcService;
#[resource]
#[export_grpc(pb::test_server::TestServer)]
#[proto_descriptor(pb::FILE_DESCRIPTOR_SET)]
impl Resource for TestService {
fn new(
_: NoDependencies, _: NoArgs, _: &mut AssemblyRuntime<'_>
) -> Result<Arc<Self>, std::convert::Infallible> {
Ok(Arc::new(Self {}))
}
}
#[tonic::async_trait]
impl pb::test_server::Test for TestService {
// ...
}
#[derive(ResourceDependencies)]
struct AutoServer {
_s: Arc<TestService>,
_server: Arc<comprehensive_grpc::server::GrpcServer>,
}
let assembly = comprehensive::Assembly::<AutoServer>::new().unwrap();
Each flag is prefixed with the name of the resource that it belongs to,
converted to kebab case (struct VerySpecialClient →
--very-special-client-). See [warm_channels::grpc_channel] and
[warm_channels::grpc::GRPCChannelConfig] for details on most
parameters.
| Flag | Default | Meaning |
|---|---|---|
PREFIXuri |
none | URI identifying the backend gRPC server. |
PREFIXconnect-uri |
none | Alternate URI for name resolution. |
PREFIXn-subchannels-want |
3 | Backend pool size. |
| etc... | More settings from [warm_channels] |
| Flag | Default | Meaning |
|---|---|---|
--grpc-port |
none | TCP port number for insecure gRPC server. If unset, plain gRPC is not served. |
--grpc-bind-addr |
:: |
Binding IP address for gRPC. Used only if --grpc_port is set. |
--grpcs-port |
none | TCP port number for secure gRPC server. If unset, gRPCs is not served. |
--grpcs-bind-addr |
:: |
Binding IP address for gRPCs. Used only if --grpcs_port is set. |
Because gRPC server reflection is very useful for diagnostics yet it is
too easy to forget to install the descriptors needed to make it happen,
[comprehensive_grpc] tries to insist that descriptors are installed
before services are added to the server.
To obtain file descriptors, put this in build.rs:
let fds_path =
std::path::PathBuf::from(std::env::var("OUT_DIR").expect("$OUT_DIR")).join("fdset.bin");
tonic_build::configure()
.file_descriptor_set_path(fds_path)
And this where you include your protos:
pub(crate) const FILE_DESCRIPTOR_SET: &[u8] = tonic::include_file_descriptor_set!("fdset");