1use anyhow::Result;
2use async_trait::async_trait;
3use std::sync::{Arc, OnceLock};
4
5use modkit::Module;
6use modkit::context::ModuleCtx;
7use modkit::contracts::{OpenApiRegistry, RestApiCapability};
8
9use crate::domain::local_client::NodesRegistryLocalClient;
10use crate::domain::service::Service;
11use nodes_registry_sdk::NodesRegistryClient;
12
13#[modkit::module(
14 name = "nodes-registry",
15 capabilities = [rest],
16 client = nodes_registry_sdk::NodesRegistryClient
17)]
18pub struct NodesRegistry {
19 service: OnceLock<Arc<Service>>,
20}
21
22impl Default for NodesRegistry {
23 fn default() -> Self {
24 Self {
25 service: OnceLock::new(),
26 }
27 }
28}
29
30#[async_trait]
31impl Module for NodesRegistry {
32 async fn init(&self, ctx: &ModuleCtx) -> Result<()> {
33 let service = Arc::new(Service::new());
35 self.service
36 .set(service.clone())
37 .map_err(|_| anyhow::anyhow!("{} module already initialized", Self::MODULE_NAME))?;
38
39 let api: Arc<dyn NodesRegistryClient> = Arc::new(NodesRegistryLocalClient::new(service));
41 ctx.client_hub().register::<dyn NodesRegistryClient>(api);
42
43 Ok(())
44 }
45}
46
47impl RestApiCapability for NodesRegistry {
48 fn register_rest(
49 &self,
50 _ctx: &ModuleCtx,
51 router: axum::Router,
52 openapi: &dyn OpenApiRegistry,
53 ) -> Result<axum::Router> {
54 let service = self
55 .service
56 .get()
57 .ok_or_else(|| anyhow::anyhow!("Service not initialized"))?
58 .clone();
59
60 let router = crate::api::rest::routes::register_routes(router, openapi, service);
61
62 tracing::info!("Nodes registry REST routes registered");
63 Ok(router)
64 }
65}