Skip to main content

reifydb_sub_server/
state.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4//! Application state shared across request handler.
5//!
6//! This module provides the shared state that is passed to all HTTP and WebSocket
7//! handler, including the database engine and query configuration.
8
9use std::time::Duration;
10
11use reifydb_engine::engine::StandardEngine;
12use reifydb_runtime::actor::system::ActorSystem;
13
14/// Configuration for query execution.
15#[derive(Debug, Clone)]
16pub struct StateConfig {
17	/// Timeout for individual query execution.
18	/// If a query takes longer than this, it will be cancelled.
19	pub query_timeout: Duration,
20	/// Timeout for entire HTTP request lifecycle.
21	/// This includes reading the request, executing the query, and writing the response.
22	pub request_timeout: Duration,
23	/// Maximum concurrent connections allowed.
24	/// New connections beyond this limit will be rejected.
25	pub max_connections: usize,
26}
27
28impl Default for StateConfig {
29	fn default() -> Self {
30		Self {
31			query_timeout: Duration::from_secs(30),
32			request_timeout: Duration::from_secs(60),
33			max_connections: 10_000,
34		}
35	}
36}
37
38impl StateConfig {
39	/// Create a new QueryConfig with default values.
40	pub fn new() -> Self {
41		Self::default()
42	}
43
44	/// Set the query timeout.
45	pub fn query_timeout(mut self, timeout: Duration) -> Self {
46		self.query_timeout = timeout;
47		self
48	}
49
50	/// Set the request timeout.
51	pub fn request_timeout(mut self, timeout: Duration) -> Self {
52		self.request_timeout = timeout;
53		self
54	}
55
56	/// Set the maximum connections.
57	pub fn max_connections(mut self, max: usize) -> Self {
58		self.max_connections = max;
59		self
60	}
61}
62
63/// Shared application state passed to all request handler.
64///
65/// This struct is cloneable and cheap to clone since `StandardEngine` uses
66/// `Arc` internally. Each handler receives a clone of this state.
67///
68/// # Example
69///
70/// ```ignore
71/// let state = AppState::new(actor_system, engine, QueryConfig::default());
72///
73/// // In an axum handler:
74/// async fn handle_query(State(state): State<AppState>, ...) {
75///     let system = state.actor_system();
76///     let engine = state.engine();
77///     // ...
78/// }
79/// ```
80#[derive(Clone)]
81pub struct AppState {
82	actor_system: ActorSystem,
83	engine: StandardEngine,
84	config: StateConfig,
85}
86
87impl AppState {
88	/// Create a new AppState with the given actor system, engine, and configuration.
89	pub fn new(actor_system: ActorSystem, engine: StandardEngine, config: StateConfig) -> Self {
90		Self {
91			actor_system,
92			engine,
93			config,
94		}
95	}
96
97	/// Get a clone of the actor system.
98	///
99	/// This is cheap since `ActorSystem` uses `Arc` internally.
100	#[inline]
101	pub fn actor_system(&self) -> ActorSystem {
102		self.actor_system.clone()
103	}
104
105	/// Get a reference to the database engine.
106	#[inline]
107	pub fn engine(&self) -> &StandardEngine {
108		&self.engine
109	}
110
111	/// Get a clone of the database engine.
112	///
113	/// This is cheap since `StandardEngine` uses `Arc` internally.
114	#[inline]
115	pub fn engine_clone(&self) -> StandardEngine {
116		self.engine.clone()
117	}
118
119	/// Get a reference to the query configuration.
120	#[inline]
121	pub fn config(&self) -> &StateConfig {
122		&self.config
123	}
124
125	/// Get the query timeout from configuration.
126	#[inline]
127	pub fn query_timeout(&self) -> Duration {
128		self.config.query_timeout
129	}
130
131	/// Get the request timeout from configuration.
132	#[inline]
133	pub fn request_timeout(&self) -> Duration {
134		self.config.request_timeout
135	}
136
137	/// Get the maximum connections from configuration.
138	#[inline]
139	pub fn max_connections(&self) -> usize {
140		self.config.max_connections
141	}
142}
143
144#[cfg(test)]
145pub mod tests {
146	use super::*;
147
148	#[test]
149	fn test_query_config_defaults() {
150		let config = StateConfig::default();
151		assert_eq!(config.query_timeout, Duration::from_secs(30));
152		assert_eq!(config.request_timeout, Duration::from_secs(60));
153		assert_eq!(config.max_connections, 10_000);
154	}
155
156	#[test]
157	fn test_query_config_builder() {
158		let config = StateConfig::new()
159			.query_timeout(Duration::from_secs(60))
160			.request_timeout(Duration::from_secs(120))
161			.max_connections(5_000);
162
163		assert_eq!(config.query_timeout, Duration::from_secs(60));
164		assert_eq!(config.request_timeout, Duration::from_secs(120));
165		assert_eq!(config.max_connections, 5_000);
166	}
167}