databuild/databuild/build_event_log.rs
2025-09-03 21:32:17 -07:00

154 lines
4.4 KiB
Rust

use crate::data_build_event::Event;
use crate::{
BuildState, DataBuildEvent, EventFilter, WantState,
};
use std::error::Error;
use std::sync::{Arc, RwLock};
trait BELStorage {
fn append_event(&mut self, event: Event) -> Result<u64, Box<dyn Error>>;
fn list_events(
&self,
since_idx: u64,
filter: EventFilter,
limit: u64,
) -> Result<Vec<DataBuildEvent>, Box<dyn Error>>;
}
struct BuildEventLog<B: BELStorage> {
storage: B,
state: Arc<RwLock<BuildState>>,
}
impl<B: BELStorage> BuildEventLog<B> {
fn create(storage: B) -> BuildEventLog<B> {
BuildEventLog {
storage,
state: Arc::new(Default::default()),
}
}
}
impl<B: BELStorage> BuildEventLog<B> {
fn append_event(&mut self, event: Event) -> Result<u64, Box<dyn Error>> {
let idx = self.storage.append_event(event.clone())?;
self.reduce(event);
Ok(idx)
}
fn reduce(&mut self, event: Event) {
match event {
Event::JobRunBuffer(e) => {}
Event::JobRunQueue(_) => {}
Event::JobRunStarted(_) => {}
Event::JobRunHeartbeat(_) => {}
Event::JobRunSuccess(_) => {}
Event::JobRunFailure(_) => {}
Event::JobRunCancel(_) => {}
Event::JobRunMissingDeps(_) => {}
Event::WantCreate(e) => {
self.state
.write()
.expect("couldn't take write lock")
.wants
.insert(e.want_id.clone(), WantState { want_id: e.want_id });
}
Event::WantCancel(_) => {}
Event::TaintCreate(_) => {}
Event::TaintDelete(_) => {}
}
}
}
mod tests {
use crate::build_event_log::{BELStorage, BuildEventLog};
use crate::data_build_event::Event;
use crate::{DataBuildEvent, EventFilter, PartitionRef, WantCreateEvent};
use std::error::Error;
use std::time::{SystemTime, UNIX_EPOCH};
struct TestBELStorage {
events: Vec<DataBuildEvent>,
}
impl TestBELStorage {
fn create() -> TestBELStorage {
TestBELStorage { events: vec![] }
}
}
impl BELStorage for TestBELStorage {
fn append_event(&mut self, event: Event) -> Result<u64, Box<dyn Error>> {
let now = SystemTime::now();
let duration_since_epoch = now.duration_since(UNIX_EPOCH)
.expect("Time went backwards");
let timestamp = duration_since_epoch.as_nanos() as u64;
let dbe = DataBuildEvent {
timestamp,
event_id: self.events.len() as u64,
event: Some(event),
};
self.events.push(dbe);
Ok(self.events.len() as u64)
}
fn list_events(
&self,
since_idx: u64,
filter: EventFilter,
limit: u64,
) -> Result<Vec<DataBuildEvent>, Box<dyn Error>> {
Ok(self.events.clone())
}
}
#[test]
fn test_hello() {
assert_eq!(2 + 3, 5);
}
#[test]
fn test_append_event() {
let storage = TestBELStorage::create();
let mut log = BuildEventLog::create(storage);
// Initial state
assert_eq!(log.storage.events.len(), 0);
let want_id = "1234".to_string();
{
let state = log.state.read().unwrap();
assert!(state.wants.get(&want_id).is_none());
}
// Given
log.append_event(Event::WantCreate(WantCreateEvent {
want_id: want_id.clone(),
root_want_id: "123".to_string(),
parent_want_id: "123".to_string(),
partitions: vec![PartitionRef {
r#ref: "".to_string(),
}],
data_timestamp: 0,
ttl_seconds: 1,
sla_seconds: 1,
source: None,
comment: None,
}))
.expect("append_event failed");
// Assert
assert_eq!(log.storage.events.len(), 1);
let state = log.state.read().expect("couldn't take read lock");
assert!(state.wants.get(&want_id).is_some(), "want_id not found");
assert_eq!(
state
.wants
.get(&want_id)
.map(|want| want.want_id.clone())
.expect("state.wants want_id not found"),
want_id,
"want_id not equal",
);
}
}