Skip to content

Commit a624d80

Browse files
committed
refactor: simplify execute() method in RenderDockerComposeTemplatesStep
- Extract helper methods to reduce complexity of execute() method - Separate database context creation from Prometheus configuration - Follow top-down, public-first module organization principles - Convert database context creation methods to associated functions (use Self::) - Database methods now return builder instead of final context for composition Key improvements: - execute() now clearly shows workflow: extract data → create contexts → apply prometheus → build - create_sqlite_contexts() and create_mysql_contexts() are pure functions focused on database config - apply_prometheus_config() applied once after database context creation (not inside each method) - Prometheus configuration independent of database choice (better separation of concerns) Method organization (no section headers): 1. new() - public constructor 2. execute() - main public method 3. Helper methods in logical order of usage 4. Associated functions at the end (extract_tracker_ports) This refactoring addresses the "chaotic" execute() method identified earlier by: - Reducing method from ~118 lines to ~40 lines - Extracting focused helper methods with single responsibilities - Making the control flow clear and readable - Improving testability through smaller, isolated functions
1 parent f2c3cb0 commit a624d80

File tree

2 files changed

+112
-91
lines changed

2 files changed

+112
-91
lines changed

src/application/steps/rendering/docker_compose_templates.rs

Lines changed: 111 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use crate::domain::environment::Environment;
3333
use crate::domain::template::TemplateManager;
3434
use crate::domain::tracker::{DatabaseConfig, TrackerConfig};
3535
use crate::infrastructure::templating::docker_compose::template::wrappers::docker_compose::{
36-
DockerComposeContext, TrackerPorts,
36+
DockerComposeContext, DockerComposeContextBuilder, TrackerPorts,
3737
};
3838
use crate::infrastructure::templating::docker_compose::template::wrappers::env::EnvContext;
3939
use crate::infrastructure::templating::docker_compose::{
@@ -72,30 +72,6 @@ impl<S> RenderDockerComposeTemplatesStep<S> {
7272
}
7373
}
7474

75-
/// Extract port numbers from tracker configuration
76-
///
77-
/// Returns a tuple of (`udp_ports`, `http_ports`, `api_port`)
78-
fn extract_tracker_ports(tracker_config: &TrackerConfig) -> (Vec<u16>, Vec<u16>, u16) {
79-
// Extract UDP tracker ports
80-
let udp_ports: Vec<u16> = tracker_config
81-
.udp_trackers
82-
.iter()
83-
.map(|tracker| tracker.bind_address.port())
84-
.collect();
85-
86-
// Extract HTTP tracker ports
87-
let http_ports: Vec<u16> = tracker_config
88-
.http_trackers
89-
.iter()
90-
.map(|tracker| tracker.bind_address.port())
91-
.collect();
92-
93-
// Extract HTTP API port
94-
let api_port = tracker_config.http_api.bind_address.port();
95-
96-
(udp_ports, http_ports, api_port)
97-
}
98-
9975
/// Execute the template rendering step
10076
///
10177
/// This will render Docker Compose templates to the build directory.
@@ -129,82 +105,33 @@ impl<S> RenderDockerComposeTemplatesStep<S> {
129105

130106
let generator = DockerComposeProjectGenerator::new(&self.build_dir, &self.template_manager);
131107

132-
// Extract admin token from environment config
133-
let admin_token = self
134-
.environment
135-
.context()
136-
.user_inputs
137-
.tracker
138-
.http_api
139-
.admin_token
140-
.clone();
141-
142-
// Extract tracker ports from configuration
143-
let tracker_config = &self.environment.context().user_inputs.tracker;
144-
let (udp_tracker_ports, http_tracker_ports, http_api_port) =
145-
Self::extract_tracker_ports(tracker_config);
146-
147-
let ports = TrackerPorts {
148-
udp_tracker_ports,
149-
http_tracker_ports,
150-
http_api_port,
151-
};
108+
let admin_token = self.extract_admin_token();
109+
let ports = self.build_tracker_ports();
152110

153111
// Create contexts based on database configuration
154112
let database_config = &self.environment.context().user_inputs.tracker.core.database;
155-
let (env_context, docker_compose_context) = match database_config {
156-
DatabaseConfig::Sqlite { .. } => {
157-
let env_context = EnvContext::new(admin_token);
158-
159-
let mut builder = DockerComposeContext::builder(ports);
160-
161-
// Add Prometheus configuration if present
162-
if let Some(prometheus_config) = &self.environment.context().user_inputs.prometheus
163-
{
164-
builder = builder.with_prometheus(prometheus_config.clone());
165-
}
166-
167-
let docker_compose_context = builder.build();
168-
(env_context, docker_compose_context)
169-
}
113+
let (env_context, builder) = match database_config {
114+
DatabaseConfig::Sqlite { .. } => Self::create_sqlite_contexts(admin_token, ports),
170115
DatabaseConfig::Mysql {
171116
port,
172117
database_name,
173118
username,
174119
password,
175120
..
176-
} => {
177-
// For MySQL, generate a secure root password (in production, this should be managed securely)
178-
let root_password = format!("{password}_root");
179-
180-
let env_context = EnvContext::new_with_mysql(
181-
admin_token,
182-
root_password.clone(),
183-
database_name.clone(),
184-
username.clone(),
185-
password.clone(),
186-
);
187-
188-
let mut builder = DockerComposeContext::builder(ports).with_mysql(
189-
root_password,
190-
database_name.clone(),
191-
username.clone(),
192-
password.clone(),
193-
*port,
194-
);
195-
196-
// Add Prometheus configuration if present
197-
if let Some(prometheus_config) = &self.environment.context().user_inputs.prometheus
198-
{
199-
builder = builder.with_prometheus(prometheus_config.clone());
200-
}
201-
202-
let docker_compose_context = builder.build();
203-
204-
(env_context, docker_compose_context)
205-
}
121+
} => Self::create_mysql_contexts(
122+
admin_token,
123+
ports,
124+
*port,
125+
database_name.clone(),
126+
username.clone(),
127+
password.clone(),
128+
),
206129
};
207130

131+
// Apply Prometheus configuration (independent of database choice)
132+
let builder = self.apply_prometheus_config(builder);
133+
let docker_compose_context = builder.build();
134+
208135
let compose_build_dir = generator
209136
.render(&env_context, &docker_compose_context)
210137
.await?;
@@ -218,6 +145,100 @@ impl<S> RenderDockerComposeTemplatesStep<S> {
218145

219146
Ok(compose_build_dir)
220147
}
148+
149+
fn extract_admin_token(&self) -> String {
150+
self.environment
151+
.context()
152+
.user_inputs
153+
.tracker
154+
.http_api
155+
.admin_token
156+
.clone()
157+
}
158+
159+
fn build_tracker_ports(&self) -> TrackerPorts {
160+
let tracker_config = &self.environment.context().user_inputs.tracker;
161+
let (udp_tracker_ports, http_tracker_ports, http_api_port) =
162+
Self::extract_tracker_ports(tracker_config);
163+
164+
TrackerPorts {
165+
udp_tracker_ports,
166+
http_tracker_ports,
167+
http_api_port,
168+
}
169+
}
170+
171+
fn create_sqlite_contexts(
172+
admin_token: String,
173+
ports: TrackerPorts,
174+
) -> (EnvContext, DockerComposeContextBuilder) {
175+
let env_context = EnvContext::new(admin_token);
176+
let builder = DockerComposeContext::builder(ports);
177+
178+
(env_context, builder)
179+
}
180+
181+
fn create_mysql_contexts(
182+
admin_token: String,
183+
ports: TrackerPorts,
184+
port: u16,
185+
database_name: String,
186+
username: String,
187+
password: String,
188+
) -> (EnvContext, DockerComposeContextBuilder) {
189+
// For MySQL, generate a secure root password (in production, this should be managed securely)
190+
let root_password = format!("{password}_root");
191+
192+
let env_context = EnvContext::new_with_mysql(
193+
admin_token,
194+
root_password.clone(),
195+
database_name.clone(),
196+
username.clone(),
197+
password.clone(),
198+
);
199+
200+
let builder = DockerComposeContext::builder(ports).with_mysql(
201+
root_password,
202+
database_name,
203+
username,
204+
password,
205+
port,
206+
);
207+
208+
(env_context, builder)
209+
}
210+
211+
fn apply_prometheus_config(
212+
&self,
213+
builder: DockerComposeContextBuilder,
214+
) -> DockerComposeContextBuilder {
215+
if let Some(prometheus_config) = &self.environment.context().user_inputs.prometheus {
216+
builder.with_prometheus(prometheus_config.clone())
217+
} else {
218+
builder
219+
}
220+
}
221+
222+
fn extract_tracker_ports(tracker_config: &TrackerConfig) -> (Vec<u16>, Vec<u16>, u16) {
223+
// Extract UDP tracker ports
224+
let udp_ports: Vec<u16> = tracker_config
225+
.udp_trackers
226+
.iter()
227+
.map(|tracker| tracker.bind_address.port())
228+
.collect();
229+
230+
// Extract HTTP tracker ports
231+
let http_ports: Vec<u16> = tracker_config
232+
.http_trackers
233+
.iter()
234+
.map(|tracker| tracker.bind_address.port())
235+
.collect();
236+
237+
// Extract HTTP API port
238+
let api_port = tracker_config.http_api.bind_address.port();
239+
240+
(udp_ports, http_ports, api_port)
241+
}
221242
}
222243

223244
#[cfg(test)]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
pub mod context;
22
pub mod template;
33

4-
pub use context::{DockerComposeContext, TrackerPorts};
4+
pub use context::{DockerComposeContext, DockerComposeContextBuilder, TrackerPorts};
55
pub use template::DockerComposeTemplate;

0 commit comments

Comments
 (0)