Back to Risingwave

How to write a service

src/docs/development/how-to-write-a-rpc-service.md

2.8.32.2 KB
Original Source

How to write a service

Quick example on how to write a service.

Define actual service

Add your service definition under src/<component>/src/rcp/service/<service_name>.rs, e.g. src/meta/src/rpc/service/health_service.rs.

rust
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.

Proto definitions

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.

Use service

Add your module in src/prost/src/lib.rs, like so:

rust
#[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

rust
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.