Skip to main content

folk_plugin_grpc/
plugin.rs

1use anyhow::Result;
2use async_trait::async_trait;
3use axum::Router;
4use folk_api::{PluginContext, RpcMethodDef, ServerPlugin};
5use tonic::transport::Server;
6use tracing::info;
7
8use crate::config::GrpcConfig;
9use crate::service::{GrpcState, grpc_handler};
10
11pub struct GrpcPlugin {
12    config: GrpcConfig,
13}
14
15impl GrpcPlugin {
16    pub fn new(config: GrpcConfig) -> Self {
17        Self { config }
18    }
19}
20
21#[async_trait]
22impl ServerPlugin for GrpcPlugin {
23    fn name(&self) -> &'static str {
24        "grpc"
25    }
26
27    async fn run(&self, ctx: PluginContext) -> Result<()> {
28        let state = GrpcState {
29            executor: ctx.executor.clone(),
30        };
31
32        let router = Router::new().fallback(grpc_handler).with_state(state);
33
34        let routes = tonic::service::Routes::from(router);
35        let mut sd = ctx.shutdown.clone();
36
37        info!(listen = %self.config.listen, "gRPC server listening");
38
39        Server::builder()
40            .add_routes(routes)
41            .serve_with_shutdown(self.config.listen, async move {
42                sd.changed().await.ok();
43            })
44            .await?;
45
46        Ok(())
47    }
48
49    fn rpc_methods(&self) -> Vec<RpcMethodDef> {
50        vec![RpcMethodDef::new(
51            "grpc.services",
52            "list registered gRPC service names",
53        )]
54    }
55}