use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum RunStatus {
Pending,
Running,
Success,
Failed,
Cancelled,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct RunRecord {
run_id: String,
experiment_id: String,
status: RunStatus,
started_at: Option<DateTime<Utc>>,
ended_at: Option<DateTime<Utc>>,
renacer_span_id: Option<String>,
}
impl RunRecord {
#[must_use]
pub fn new(run_id: impl Into<String>, experiment_id: impl Into<String>) -> Self {
Self {
run_id: run_id.into(),
experiment_id: experiment_id.into(),
status: RunStatus::Pending,
started_at: None,
ended_at: None,
renacer_span_id: None,
}
}
#[must_use]
pub fn builder(
run_id: impl Into<String>,
experiment_id: impl Into<String>,
) -> RunRecordBuilder {
RunRecordBuilder::new(run_id, experiment_id)
}
#[must_use]
pub fn run_id(&self) -> &str {
&self.run_id
}
#[must_use]
pub fn experiment_id(&self) -> &str {
&self.experiment_id
}
#[must_use]
pub const fn status(&self) -> RunStatus {
self.status
}
#[must_use]
pub const fn started_at(&self) -> Option<DateTime<Utc>> {
self.started_at
}
#[must_use]
pub const fn ended_at(&self) -> Option<DateTime<Utc>> {
self.ended_at
}
#[must_use]
pub fn renacer_span_id(&self) -> Option<&str> {
self.renacer_span_id.as_deref()
}
pub fn start(&mut self) {
self.status = RunStatus::Running;
self.started_at = Some(Utc::now());
}
pub fn complete(&mut self, status: RunStatus) {
self.status = status;
self.ended_at = Some(Utc::now());
}
}
#[derive(Debug)]
#[allow(clippy::struct_field_names)]
pub struct RunRecordBuilder {
run_id: String,
experiment_id: String,
renacer_span_id: Option<String>,
}
impl RunRecordBuilder {
#[must_use]
pub fn new(run_id: impl Into<String>, experiment_id: impl Into<String>) -> Self {
Self { run_id: run_id.into(), experiment_id: experiment_id.into(), renacer_span_id: None }
}
#[must_use]
pub fn renacer_span_id(mut self, span_id: impl Into<String>) -> Self {
self.renacer_span_id = Some(span_id.into());
self
}
#[must_use]
pub fn build(self) -> RunRecord {
RunRecord {
run_id: self.run_id,
experiment_id: self.experiment_id,
status: RunStatus::Pending,
started_at: None,
ended_at: None,
renacer_span_id: self.renacer_span_id,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_run_status_default() {
let run = RunRecord::new("run-1", "exp-1");
assert_eq!(run.status(), RunStatus::Pending);
}
#[test]
fn test_run_lifecycle() {
let mut run = RunRecord::new("run-1", "exp-1");
run.start();
assert_eq!(run.status(), RunStatus::Running);
run.complete(RunStatus::Success);
assert_eq!(run.status(), RunStatus::Success);
}
}