reifydb_sub_api/
subsystem.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4use std::any::Any;
5
6use async_trait::async_trait;
7use reifydb_core::{
8	interceptor::StandardInterceptorBuilder,
9	interface::{CommandTransaction, version::HasVersion},
10	ioc::IocContainer,
11};
12
13/// Uniform interface that all subsystems must implement
14///
15/// This trait provides a consistent lifecycle and monitoring interface
16/// for all subsystems managed by the Database.
17#[async_trait]
18pub trait Subsystem: Send + Sync + Any + HasVersion {
19	/// Get the unique name of this subsystem
20	fn name(&self) -> &'static str;
21	/// Start the subsystem
22	///
23	/// This method should initialize the subsystem and start any background
24	/// threads or processes. It should be idempotent - calling start() on
25	/// an already running subsystem should succeed without side effects.
26	async fn start(&mut self) -> reifydb_core::Result<()>;
27	/// Shutdown the subsystem
28	///
29	/// This method should gracefully shut down the subsystem and clean up
30	/// any resources. This is a terminal operation - once shutdown, the
31	/// subsystem cannot be restarted. It should be idempotent - calling
32	/// shutdown() on an already shutdown subsystem should succeed without
33	/// side effects.
34	async fn shutdown(&mut self) -> reifydb_core::Result<()>;
35
36	/// Check if the subsystem is currently running
37	fn is_running(&self) -> bool;
38
39	/// Get the current health status of the subsystem
40	///
41	/// This should provide information about the subsystem's operational
42	/// status and any errors or warnings.
43	fn health_status(&self) -> HealthStatus;
44
45	/// Get a reference to self as Any for downcasting
46	fn as_any(&self) -> &dyn Any;
47
48	/// Get a mutable reference to self as Any for downcasting
49	fn as_any_mut(&mut self) -> &mut dyn Any;
50}
51
52/// Factory trait for creating subsystems with IoC support
53#[async_trait]
54pub trait SubsystemFactory<CT: CommandTransaction>: Send {
55	fn provide_interceptors(
56		&self,
57		builder: StandardInterceptorBuilder<CT>,
58		_ioc: &IocContainer,
59	) -> StandardInterceptorBuilder<CT> {
60		builder
61	}
62
63	async fn create(self: Box<Self>, ioc: &IocContainer) -> reifydb_core::Result<Box<dyn Subsystem>>;
64}
65
66#[derive(Debug, Clone, PartialEq)]
67pub enum HealthStatus {
68	Healthy,
69	Warning {
70		description: String,
71	},
72	Degraded {
73		description: String,
74	},
75	Failed {
76		description: String,
77	},
78	Unknown,
79}
80
81impl HealthStatus {
82	pub fn is_healthy(&self) -> bool {
83		matches!(self, HealthStatus::Healthy)
84	}
85
86	pub fn is_failed(&self) -> bool {
87		matches!(self, HealthStatus::Failed { .. })
88	}
89
90	pub fn description(&self) -> &str {
91		match self {
92			HealthStatus::Healthy => "Healthy",
93			HealthStatus::Warning {
94				description: message,
95			} => message,
96			HealthStatus::Degraded {
97				description: message,
98			} => message,
99			HealthStatus::Failed {
100				description: message,
101			} => message,
102			HealthStatus::Unknown => "Unknown",
103		}
104	}
105}