trueno_db/experiment/
run_record.rs1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8pub enum RunStatus {
9 Pending,
11 Running,
13 Success,
15 Failed,
17 Cancelled,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
26pub struct RunRecord {
27 run_id: String,
28 experiment_id: String,
29 status: RunStatus,
30 started_at: Option<DateTime<Utc>>,
31 ended_at: Option<DateTime<Utc>>,
32 renacer_span_id: Option<String>,
33}
34
35impl RunRecord {
36 #[must_use]
43 pub fn new(run_id: impl Into<String>, experiment_id: impl Into<String>) -> Self {
44 Self {
45 run_id: run_id.into(),
46 experiment_id: experiment_id.into(),
47 status: RunStatus::Pending,
48 started_at: None,
49 ended_at: None,
50 renacer_span_id: None,
51 }
52 }
53
54 #[must_use]
56 pub fn builder(
57 run_id: impl Into<String>,
58 experiment_id: impl Into<String>,
59 ) -> RunRecordBuilder {
60 RunRecordBuilder::new(run_id, experiment_id)
61 }
62
63 #[must_use]
65 pub fn run_id(&self) -> &str {
66 &self.run_id
67 }
68
69 #[must_use]
71 pub fn experiment_id(&self) -> &str {
72 &self.experiment_id
73 }
74
75 #[must_use]
77 pub const fn status(&self) -> RunStatus {
78 self.status
79 }
80
81 #[must_use]
83 pub const fn started_at(&self) -> Option<DateTime<Utc>> {
84 self.started_at
85 }
86
87 #[must_use]
89 pub const fn ended_at(&self) -> Option<DateTime<Utc>> {
90 self.ended_at
91 }
92
93 #[must_use]
95 pub fn renacer_span_id(&self) -> Option<&str> {
96 self.renacer_span_id.as_deref()
97 }
98
99 pub fn start(&mut self) {
103 self.status = RunStatus::Running;
104 self.started_at = Some(Utc::now());
105 }
106
107 pub fn complete(&mut self, status: RunStatus) {
115 self.status = status;
116 self.ended_at = Some(Utc::now());
117 }
118}
119
120#[derive(Debug)]
122#[allow(clippy::struct_field_names)]
123pub struct RunRecordBuilder {
124 run_id: String,
125 experiment_id: String,
126 renacer_span_id: Option<String>,
127}
128
129impl RunRecordBuilder {
130 #[must_use]
132 pub fn new(run_id: impl Into<String>, experiment_id: impl Into<String>) -> Self {
133 Self { run_id: run_id.into(), experiment_id: experiment_id.into(), renacer_span_id: None }
134 }
135
136 #[must_use]
138 pub fn renacer_span_id(mut self, span_id: impl Into<String>) -> Self {
139 self.renacer_span_id = Some(span_id.into());
140 self
141 }
142
143 #[must_use]
145 pub fn build(self) -> RunRecord {
146 RunRecord {
147 run_id: self.run_id,
148 experiment_id: self.experiment_id,
149 status: RunStatus::Pending,
150 started_at: None,
151 ended_at: None,
152 renacer_span_id: self.renacer_span_id,
153 }
154 }
155}
156
157#[cfg(test)]
158mod tests {
159 use super::*;
160
161 #[test]
162 fn test_run_status_default() {
163 let run = RunRecord::new("run-1", "exp-1");
164 assert_eq!(run.status(), RunStatus::Pending);
165 }
166
167 #[test]
168 fn test_run_lifecycle() {
169 let mut run = RunRecord::new("run-1", "exp-1");
170 run.start();
171 assert_eq!(run.status(), RunStatus::Running);
172 run.complete(RunStatus::Success);
173 assert_eq!(run.status(), RunStatus::Success);
174 }
175}