Skip to main content

modkit/runtime/
grpc_installers.rs

1use parking_lot::Mutex;
2
3use crate::contracts::RegisterGrpcServiceFn;
4
5/// Installers for a specific module (module name + service installers).
6#[derive(Default)]
7pub struct ModuleInstallers {
8    pub module_name: String,
9    pub installers: Vec<RegisterGrpcServiceFn>,
10}
11
12/// Grouped installers for all modules in the process.
13#[derive(Default)]
14pub struct GrpcInstallerData {
15    pub modules: Vec<ModuleInstallers>,
16}
17
18/// Runtime-owned store for gRPC service installers.
19///
20/// This replaces the previous global static storage with a proper
21/// runtime-scoped type that gets injected into the `grpc-hub` module.
22pub struct GrpcInstallerStore {
23    inner: Mutex<Option<GrpcInstallerData>>,
24}
25
26impl GrpcInstallerStore {
27    #[must_use]
28    pub fn new() -> Self {
29        Self {
30            inner: Mutex::new(None),
31        }
32    }
33
34    /// Set installers once. Fails if already initialized.
35    ///
36    /// # Errors
37    /// Returns an error if installers have already been initialized.
38    pub fn set(&self, data: GrpcInstallerData) -> anyhow::Result<()> {
39        let mut guard = self.inner.lock();
40        if guard.is_some() {
41            anyhow::bail!("gRPC installers already initialized");
42        }
43        *guard = Some(data);
44        Ok(())
45    }
46
47    /// Consume and return all installers grouped by module.
48    pub fn take(&self) -> Option<GrpcInstallerData> {
49        let mut guard = self.inner.lock();
50        guard.take()
51    }
52
53    /// Check if installers are present (optional helper).
54    #[allow(dead_code)]
55    pub fn is_empty(&self) -> bool {
56        self.inner.lock().is_none()
57    }
58}
59
60impl Default for GrpcInstallerStore {
61    fn default() -> Self {
62        Self::new()
63    }
64}