Skip to main content

reifydb_sub_server_http/
factory.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use std::{sync::Arc, time::Duration};
5
6use reifydb_auth::{
7	registry::AuthenticationRegistry,
8	service::{AuthService, AuthServiceConfig},
9};
10use reifydb_core::util::ioc::IocContainer;
11use reifydb_engine::engine::StandardEngine;
12use reifydb_runtime::SharedRuntime;
13use reifydb_sub_api::subsystem::{Subsystem, SubsystemFactory};
14use reifydb_sub_server::{
15	interceptor::RequestInterceptorChain,
16	state::{AppState, StateConfig},
17};
18use reifydb_type::Result;
19
20use crate::subsystem::HttpSubsystem;
21
22pub struct HttpConfigurator {
23	bind_addr: Option<String>,
24	admin_bind_addr: Option<String>,
25	max_connections: usize,
26	query_timeout: Duration,
27	request_timeout: Duration,
28	runtime: Option<SharedRuntime>,
29}
30
31impl Default for HttpConfigurator {
32	fn default() -> Self {
33		Self::new()
34	}
35}
36
37impl HttpConfigurator {
38	pub fn new() -> Self {
39		Self {
40			bind_addr: None,
41			admin_bind_addr: None,
42			max_connections: 10_000,
43			query_timeout: Duration::from_secs(30),
44			request_timeout: Duration::from_secs(60),
45			runtime: None,
46		}
47	}
48
49	pub fn bind_addr(mut self, addr: impl Into<String>) -> Self {
50		self.bind_addr = Some(addr.into());
51		self
52	}
53
54	pub fn admin_bind_addr(mut self, addr: impl Into<String>) -> Self {
55		self.admin_bind_addr = Some(addr.into());
56		self
57	}
58
59	pub fn max_connections(mut self, max: usize) -> Self {
60		self.max_connections = max;
61		self
62	}
63
64	pub fn query_timeout(mut self, timeout: Duration) -> Self {
65		self.query_timeout = timeout;
66		self
67	}
68
69	pub fn request_timeout(mut self, timeout: Duration) -> Self {
70		self.request_timeout = timeout;
71		self
72	}
73
74	pub fn runtime(mut self, runtime: SharedRuntime) -> Self {
75		self.runtime = Some(runtime);
76		self
77	}
78
79	pub(crate) fn configure(self) -> HttpConfig {
80		HttpConfig {
81			bind_addr: self.bind_addr,
82			admin_bind_addr: self.admin_bind_addr,
83			max_connections: self.max_connections,
84			query_timeout: self.query_timeout,
85			request_timeout: self.request_timeout,
86			runtime: self.runtime,
87		}
88	}
89}
90
91#[derive(Clone, Debug)]
92pub struct HttpConfig {
93	pub bind_addr: Option<String>,
94
95	pub admin_bind_addr: Option<String>,
96
97	pub max_connections: usize,
98
99	pub query_timeout: Duration,
100
101	pub request_timeout: Duration,
102
103	pub runtime: Option<SharedRuntime>,
104}
105
106impl Default for HttpConfig {
107	fn default() -> Self {
108		HttpConfigurator::new().configure()
109	}
110}
111
112pub struct HttpSubsystemFactory {
113	config_fn: Box<dyn FnOnce() -> HttpConfig + Send>,
114}
115
116impl HttpSubsystemFactory {
117	pub fn new<F>(configurator: F) -> Self
118	where
119		F: FnOnce(HttpConfigurator) -> HttpConfigurator + Send + 'static,
120	{
121		Self {
122			config_fn: Box::new(move || configurator(HttpConfigurator::new()).configure()),
123		}
124	}
125}
126
127impl SubsystemFactory for HttpSubsystemFactory {
128	fn create(self: Box<Self>, ioc: &IocContainer) -> Result<Box<dyn Subsystem>> {
129		let config = (self.config_fn)();
130
131		let engine = ioc.resolve::<StandardEngine>()?;
132		let ioc_runtime = ioc.resolve::<SharedRuntime>()?;
133		let interceptors = ioc.resolve::<RequestInterceptorChain>().unwrap_or_default();
134
135		let query_config = StateConfig::new()
136			.query_timeout(config.query_timeout)
137			.request_timeout(config.request_timeout)
138			.max_connections(config.max_connections);
139
140		let runtime = config.runtime.unwrap_or(ioc_runtime);
141
142		let auth_service = AuthService::new(
143			Arc::new(engine.clone()),
144			Arc::new(AuthenticationRegistry::new(runtime.clock().clone())),
145			runtime.rng().clone(),
146			runtime.clock().clone(),
147			AuthServiceConfig::default(),
148		);
149
150		let state = AppState::new(
151			runtime.actor_system(),
152			engine,
153			auth_service,
154			query_config,
155			interceptors,
156			runtime.clock().clone(),
157			runtime.rng().clone(),
158		);
159		let subsystem =
160			HttpSubsystem::new(config.bind_addr.clone(), config.admin_bind_addr.clone(), state, runtime);
161
162		Ok(Box::new(subsystem))
163	}
164}