Skip to main content

mecha10_dev/services/topology/
ports.rs

1//! Redis connection and service port extraction
2
3use anyhow::Result;
4use regex::Regex;
5
6use crate::types::ProjectConfig;
7
8use super::{RedisInfo, ServiceInfo, TopologyService};
9
10impl TopologyService {
11    /// Parse Redis URL into components
12    ///
13    /// Note: This method is public primarily for testing purposes.
14    pub fn parse_redis_url(&self, url: &str) -> Result<RedisInfo> {
15        // Handle redis://host:port format
16        let url_pattern = Regex::new(r"redis://([^:]+):(\d+)")?;
17
18        if let Some(caps) = url_pattern.captures(url) {
19            let host = caps.get(1).map(|m| m.as_str()).unwrap_or("localhost");
20            let port = caps.get(2).and_then(|m| m.as_str().parse::<u16>().ok()).unwrap_or(6379);
21
22            Ok(RedisInfo {
23                url: url.to_string(),
24                host: host.to_string(),
25                port,
26            })
27        } else {
28            // Default fallback
29            Ok(RedisInfo {
30                url: url.to_string(),
31                host: "localhost".to_string(),
32                port: 6379,
33            })
34        }
35    }
36
37    /// Extract service port information from config
38    pub(super) fn extract_services(&self, config: &ProjectConfig) -> Vec<ServiceInfo> {
39        let mut services = Vec::new();
40
41        // HTTP API service
42        if let Some(http_api) = &config.services.http_api {
43            services.push(ServiceInfo {
44                name: "HTTP API".to_string(),
45                host: http_api.host.clone(),
46                port: http_api.port,
47            });
48        }
49
50        // Database service
51        if let Some(db) = &config.services.database {
52            // Try to parse postgres://host:port or similar
53            if let Some(port) = self.extract_port_from_url(&db.url) {
54                services.push(ServiceInfo {
55                    name: "Database".to_string(),
56                    host: self
57                        .extract_host_from_url(&db.url)
58                        .unwrap_or_else(|| "localhost".to_string()),
59                    port,
60                });
61            }
62        }
63
64        services
65    }
66
67    /// Extract host from a URL string
68    fn extract_host_from_url(&self, url: &str) -> Option<String> {
69        let re = Regex::new(r"://([^:/@]+)").ok()?;
70        re.captures(url)
71            .and_then(|caps| caps.get(1).map(|m| m.as_str().to_string()))
72    }
73
74    /// Extract port from a URL string
75    fn extract_port_from_url(&self, url: &str) -> Option<u16> {
76        let re = Regex::new(r":(\d+)").ok()?;
77        re.captures(url)
78            .and_then(|caps| caps.get(1))
79            .and_then(|m| m.as_str().parse().ok())
80    }
81}