reifydb_sub_server/
state.rs

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