folk_plugin_grpc/
plugin.rs1use 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}