187 lines
No EOL
5.5 KiB
Rust
187 lines
No EOL
5.5 KiB
Rust
use crate::*;
|
|
use async_trait::async_trait;
|
|
use std::error::Error as StdError;
|
|
use uuid::Uuid;
|
|
|
|
pub mod stdout;
|
|
pub mod sqlite;
|
|
pub mod postgres;
|
|
pub mod writer;
|
|
pub mod mock;
|
|
|
|
#[derive(Debug)]
|
|
pub enum BuildEventLogError {
|
|
DatabaseError(String),
|
|
SerializationError(String),
|
|
ConnectionError(String),
|
|
QueryError(String),
|
|
}
|
|
|
|
impl std::fmt::Display for BuildEventLogError {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
BuildEventLogError::DatabaseError(msg) => write!(f, "Database error: {}", msg),
|
|
BuildEventLogError::SerializationError(msg) => write!(f, "Serialization error: {}", msg),
|
|
BuildEventLogError::ConnectionError(msg) => write!(f, "Connection error: {}", msg),
|
|
BuildEventLogError::QueryError(msg) => write!(f, "Query error: {}", msg),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl StdError for BuildEventLogError {}
|
|
|
|
pub type Result<T> = std::result::Result<T, BuildEventLogError>;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct QueryResult {
|
|
pub columns: Vec<String>,
|
|
pub rows: Vec<Vec<String>>,
|
|
}
|
|
|
|
// Summary types for list endpoints
|
|
#[derive(Debug, Clone)]
|
|
pub struct BuildRequestSummary {
|
|
pub build_request_id: String,
|
|
pub status: BuildRequestStatus,
|
|
pub requested_partitions: Vec<String>,
|
|
pub created_at: i64,
|
|
pub updated_at: i64,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct PartitionSummary {
|
|
pub partition_ref: String,
|
|
pub status: PartitionStatus,
|
|
pub updated_at: i64,
|
|
pub build_request_id: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct ActivitySummary {
|
|
pub active_builds_count: u32,
|
|
pub recent_builds: Vec<BuildRequestSummary>,
|
|
pub recent_partitions: Vec<PartitionSummary>,
|
|
pub total_partitions_count: u32,
|
|
}
|
|
|
|
#[async_trait]
|
|
pub trait BuildEventLog: Send + Sync {
|
|
// Append new event to the log
|
|
async fn append_event(&self, event: BuildEvent) -> Result<()>;
|
|
|
|
// Query events by build request
|
|
async fn get_build_request_events(
|
|
&self,
|
|
build_request_id: &str,
|
|
since: Option<i64>
|
|
) -> Result<Vec<BuildEvent>>;
|
|
|
|
// Query events by partition
|
|
async fn get_partition_events(
|
|
&self,
|
|
partition_ref: &str,
|
|
since: Option<i64>
|
|
) -> Result<Vec<BuildEvent>>;
|
|
|
|
// Query events by job run
|
|
async fn get_job_run_events(
|
|
&self,
|
|
job_run_id: &str
|
|
) -> Result<Vec<BuildEvent>>;
|
|
|
|
// Query events in time range
|
|
async fn get_events_in_range(
|
|
&self,
|
|
start_time: i64,
|
|
end_time: i64
|
|
) -> Result<Vec<BuildEvent>>;
|
|
|
|
// Execute raw SQL queries (for dashboard and debugging)
|
|
async fn execute_query(&self, query: &str) -> Result<QueryResult>;
|
|
|
|
// Get latest partition availability status
|
|
async fn get_latest_partition_status(
|
|
&self,
|
|
partition_ref: &str
|
|
) -> Result<Option<(PartitionStatus, i64)>>; // status and timestamp
|
|
|
|
// Check if partition is being built by another request
|
|
async fn get_active_builds_for_partition(
|
|
&self,
|
|
partition_ref: &str
|
|
) -> Result<Vec<String>>; // build request IDs
|
|
|
|
// Initialize/setup the storage backend
|
|
async fn initialize(&self) -> Result<()>;
|
|
|
|
// List recent build requests with pagination and filtering
|
|
async fn list_build_requests(
|
|
&self,
|
|
limit: u32,
|
|
offset: u32,
|
|
status_filter: Option<BuildRequestStatus>,
|
|
) -> Result<(Vec<BuildRequestSummary>, u32)>;
|
|
|
|
// List recent partitions with pagination and filtering
|
|
async fn list_recent_partitions(
|
|
&self,
|
|
limit: u32,
|
|
offset: u32,
|
|
status_filter: Option<PartitionStatus>,
|
|
) -> Result<(Vec<PartitionSummary>, u32)>;
|
|
|
|
// Get aggregated activity summary for dashboard
|
|
async fn get_activity_summary(&self) -> Result<ActivitySummary>;
|
|
|
|
// Get the build request ID that created an available partition
|
|
async fn get_build_request_for_available_partition(
|
|
&self,
|
|
partition_ref: &str
|
|
) -> Result<Option<String>>; // build request ID that made partition available
|
|
}
|
|
|
|
// Helper function to generate event ID
|
|
pub fn generate_event_id() -> String {
|
|
Uuid::new_v4().to_string()
|
|
}
|
|
|
|
// Helper function to get current timestamp in nanoseconds
|
|
pub fn current_timestamp_nanos() -> i64 {
|
|
std::time::SystemTime::now()
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
.unwrap()
|
|
.as_nanos() as i64
|
|
}
|
|
|
|
// Helper function to create build event with metadata
|
|
pub fn create_build_event(
|
|
build_request_id: String,
|
|
event_type: crate::build_event::EventType,
|
|
) -> BuildEvent {
|
|
BuildEvent {
|
|
event_id: generate_event_id(),
|
|
timestamp: current_timestamp_nanos(),
|
|
build_request_id,
|
|
event_type: Some(event_type),
|
|
}
|
|
}
|
|
|
|
// Parse build event log URI and create appropriate implementation
|
|
pub async fn create_build_event_log(uri: &str) -> Result<Box<dyn BuildEventLog>> {
|
|
if uri == "stdout" {
|
|
Ok(Box::new(stdout::StdoutBuildEventLog::new()))
|
|
} else if uri.starts_with("sqlite://") {
|
|
let path = &uri[9..]; // Remove "sqlite://" prefix
|
|
let log = sqlite::SqliteBuildEventLog::new(path).await?;
|
|
log.initialize().await?;
|
|
Ok(Box::new(log))
|
|
} else if uri.starts_with("postgres://") {
|
|
let log = postgres::PostgresBuildEventLog::new(uri).await?;
|
|
log.initialize().await?;
|
|
Ok(Box::new(log))
|
|
} else {
|
|
Err(BuildEventLogError::ConnectionError(
|
|
format!("Unsupported build event log URI: {}", uri)
|
|
))
|
|
}
|
|
} |