Skip to main content

reifydb_sub_server_http/
factory.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4//! Factory for creating HTTP subsystem instances.
5
6use std::{sync::Arc, time::Duration};
7
8use reifydb_auth::{
9	registry::AuthenticationRegistry,
10	service::{AuthService, AuthServiceConfig},
11};
12use reifydb_core::util::ioc::IocContainer;
13use reifydb_engine::engine::StandardEngine;
14use reifydb_runtime::SharedRuntime;
15use reifydb_sub_api::subsystem::{Subsystem, SubsystemFactory};
16use reifydb_sub_server::{
17	interceptor::RequestInterceptorChain,
18	state::{AppState, StateConfig},
19};
20use reifydb_type::Result;
21
22use crate::subsystem::HttpSubsystem;
23
24/// Configuration for the HTTP server subsystem.
25#[derive(Clone, Debug)]
26pub struct HttpConfig {
27	/// Address to bind the HTTP server to (e.g., "0.0.0.0:8091").
28	pub bind_addr: Option<String>,
29	/// Address to bind the admin HTTP server to (e.g., "127.0.0.1:9091").
30	/// When set, admin operations are only available on this port.
31	/// When not set, admin operations are not available.
32	pub admin_bind_addr: Option<String>,
33	/// Maximum number of concurrent connections.
34	pub max_connections: usize,
35	/// Timeout for query execution.
36	pub query_timeout: Duration,
37	/// Timeout for entire request lifecycle.
38	pub request_timeout: Duration,
39	/// Optional shared runtime .
40	pub runtime: Option<SharedRuntime>,
41}
42
43impl Default for HttpConfig {
44	fn default() -> Self {
45		Self {
46			bind_addr: None,
47			admin_bind_addr: None,
48			max_connections: 10_000,
49			query_timeout: Duration::from_secs(30),
50			request_timeout: Duration::from_secs(60),
51			runtime: None,
52		}
53	}
54}
55
56impl HttpConfig {
57	/// Create a new HTTP config with default values.
58	pub fn new() -> Self {
59		Self::default()
60	}
61
62	/// Set the bind address.
63	pub fn bind_addr(mut self, addr: impl Into<String>) -> Self {
64		self.bind_addr = Some(addr.into());
65		self
66	}
67
68	/// Set the admin bind address.
69	/// When set, admin operations are served on this separate port.
70	pub fn admin_bind_addr(mut self, addr: impl Into<String>) -> Self {
71		self.admin_bind_addr = Some(addr.into());
72		self
73	}
74
75	/// Set the maximum number of connections.
76	pub fn max_connections(mut self, max: usize) -> Self {
77		self.max_connections = max;
78		self
79	}
80
81	/// Set the query timeout.
82	pub fn query_timeout(mut self, timeout: Duration) -> Self {
83		self.query_timeout = timeout;
84		self
85	}
86
87	/// Set the request timeout.
88	pub fn request_timeout(mut self, timeout: Duration) -> Self {
89		self.request_timeout = timeout;
90		self
91	}
92
93	/// Set the shared runtime.
94	pub fn runtime(mut self, runtime: SharedRuntime) -> Self {
95		self.runtime = Some(runtime);
96		self
97	}
98}
99
100/// Factory for creating HTTP subsystem instances.
101pub struct HttpSubsystemFactory {
102	config: HttpConfig,
103}
104
105impl HttpSubsystemFactory {
106	/// Create a new HTTP subsystem factory with the given configuration.
107	pub fn new(config: HttpConfig) -> Self {
108		Self {
109			config,
110		}
111	}
112}
113
114impl SubsystemFactory for HttpSubsystemFactory {
115	fn create(self: Box<Self>, ioc: &IocContainer) -> Result<Box<dyn Subsystem>> {
116		let engine = ioc.resolve::<StandardEngine>()?;
117		let ioc_runtime = ioc.resolve::<SharedRuntime>()?;
118		let interceptors = ioc.resolve::<RequestInterceptorChain>().unwrap_or_default();
119
120		let query_config = StateConfig::new()
121			.query_timeout(self.config.query_timeout)
122			.request_timeout(self.config.request_timeout)
123			.max_connections(self.config.max_connections);
124
125		let runtime = self.config.runtime.unwrap_or(ioc_runtime);
126
127		let auth_service = AuthService::new(
128			Arc::new(engine.clone()),
129			Arc::new(AuthenticationRegistry::new(runtime.clock().clone())),
130			runtime.rng().clone(),
131			runtime.clock().clone(),
132			AuthServiceConfig::default(),
133		);
134
135		let state = AppState::new(
136			runtime.actor_system(),
137			engine,
138			auth_service,
139			query_config,
140			interceptors,
141			runtime.clock().clone(),
142		);
143		let subsystem = HttpSubsystem::new(
144			self.config.bind_addr.clone(),
145			self.config.admin_bind_addr.clone(),
146			state,
147			runtime,
148		);
149
150		Ok(Box::new(subsystem))
151	}
152}