use crate::models::health::{HealthCheckConfig, HealthResult};
use chrono::{DateTime, Utc, Duration};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Service {
pub id: String,
pub name: String,
pub service_type: ServiceType,
pub source: DetectionSource,
pub host: String,
pub port: u16,
pub additional_ports: Vec<u16>,
pub pid: Option<u32>,
pub process_name: Option<String>,
pub command_line: Option<String>,
pub container_id: Option<String>,
pub systemd_unit: Option<String>,
pub log_file_path: Option<String>,
pub health_check: HealthCheckConfig,
pub project_path: String,
pub tags: Vec<String>,
pub dependencies: Vec<String>,
#[serde(skip)]
pub health_status: Option<HealthResult>,
pub first_seen: DateTime<Utc>,
pub last_seen: DateTime<Utc>,
}
impl Service {
pub fn new(
name: String,
service_type: ServiceType,
host: String,
port: u16,
source: DetectionSource,
project_path: String,
) -> Self {
let now = Utc::now();
let id = format!("{}:{}", name.to_lowercase().replace(' ', "-"), port);
Self {
id,
name,
service_type,
source,
host,
port,
additional_ports: Vec::new(),
pid: None,
process_name: None,
command_line: None,
container_id: None,
systemd_unit: None,
log_file_path: None,
health_check: HealthCheckConfig::default(),
project_path,
tags: Vec::new(),
dependencies: Vec::new(),
health_status: None,
first_seen: now,
last_seen: now,
}
}
pub fn is_healthy(&self) -> bool {
self.health_status
.as_ref()
.map(|h| matches!(h.status, crate::models::HealthStatus::Healthy))
.unwrap_or(false)
}
pub fn uptime(&self) -> Duration {
Utc::now() - self.first_seen
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ServiceType {
HttpServer,
Database(DatabaseType),
MessageQueue(QueueType),
Cache(CacheType),
Search(SearchType),
DockerContainer,
Custom,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum DatabaseType {
Postgres,
MySQL,
MongoDB,
SQLite,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum QueueType {
RabbitMQ,
Kafka,
Redis,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum CacheType {
Redis,
Memcached,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum SearchType {
Elasticsearch,
Meilisearch,
Typesense,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum DetectionSource {
ExplicitConfig,
DockerCompose,
PortScan,
ProcessScan,
AutoDetected,
}