src/docs/development/how-to-write-a-rpc-service.md
Quick example on how to write a service.
Add your service definition under src/<component>/src/rcp/service/<service_name>.rs, e.g. src/meta/src/rpc/service/health_service.rs.
pub struct HealthServiceImpl {}
impl HealthServiceImpl {
pub fn new() -> Self {
Self {}
}
}
#[async_trait::async_trait]
impl Health for HealthServiceImpl {
async fn check(
&self,
_request: Request<HealthCheckRequest>,
) -> Result<Response<HealthCheckResponse>, Status> {
// Reply serving as long as tonic service is started
Ok(Response::new(HealthCheckResponse {
status: ServingStatus::Serving as i32,
}))
}
}
Also see the other services in src/<component>/src/rcp/service/ for further examples. Above service defines a HealthCheckRequest and a HealthCheckResponse, which use proto messages. We have to define these proto messages.
Add definition in proto/health.proto. For above service it is
package health;
message HealthCheckRequest {
string service = 1;
}
message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
}
ServingStatus status = 1;
}
service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
}
Make sure to lint your file using buf.
Add your module in src/prost/src/lib.rs, like so:
#[rustfmt::skip]
#[cfg_attr(madsim, path = "sim/health.rs")]
pub mod health;
Add your proto file "health" in src/prost/build.rs.
Add the module in src/meta/src/rpc/service/mod.rs.
Use your service in src/meta/src/rpc/server.rs, like
let health_srv = HealthServiceImpl::new();
tokio::spawn(async move {
tonic::transport::Server::builder()
.layer(MetricsMiddlewareLayer::new(meta_metrics.clone()))
.add_service(HealthServer::new(health_srv))
.serve(address_info.listen_addr)
.await
.unwrap();
});
To use your service you need to generate some boilerplate code, like e.g. the service definition. Running risedev d should generate this boilerplate code.