1use std::time::SystemTime;
2
3use derive_ex::Ex;
4use ordered_float::OrderedFloat;
5use serde::{Deserialize, Serialize};
6use thiserror::Error;
7
8#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
10pub struct FileInfo {
11 pub path: String,
12 pub is_dir: bool,
13 pub file_size: Option<i64>,
14}
15
16#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
18pub struct Run {
19 pub info: RunInfo,
20 pub data: RunData,
21 pub inputs: RunInputs,
22}
23
24#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
26pub struct RunInfo {
27 pub run_id: String,
28 pub run_name: String,
29 pub experiment_id: String,
30 pub status: RunStatus,
31 pub start_time: Timestamp,
32 pub end_time: Option<Timestamp>,
33 pub artifact_uri: String,
34 pub lifecycle_stage: String,
35}
36
37#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
39pub struct RunData {
40 #[serde(default)]
41 pub metrics: Vec<Metric>,
42 #[serde(default)]
43 pub params: Vec<Param>,
44 #[serde(default)]
45 pub tags: Vec<RunTag>,
46}
47
48#[derive(Serialize, Deserialize, Debug, Clone, Ex)]
50#[derive_ex(Eq, PartialEq, Ord, PartialOrd)]
51pub struct Metric {
52 pub key: String,
53 #[ord(key = OrderedFloat($))]
54 pub value: f64,
55 pub timestamp: Timestamp,
56 pub step: Option<i64>,
57}
58
59#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
61pub struct Param {
62 pub key: String,
63 pub value: String,
64}
65
66#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
68pub struct RunInputs {
69 #[serde(default)]
70 pub dataset_inputs: Vec<DatasetInput>,
71}
72
73#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
75pub struct DatasetInput {
76 pub tags: Vec<InputTag>,
77 pub dataset: Dataset,
78}
79
80#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
82pub struct InputTag {
83 pub key: String,
84 pub value: String,
85}
86
87#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
89pub struct Dataset {
90 pub name: String,
91 pub digest: String,
92 pub source_type: String,
93 pub source: String,
94 pub schema: Option<String>,
95 pub profile: Option<String>,
96}
97
98#[derive(Debug, Serialize, Deserialize, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
100#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
101pub enum RunStatus {
102 Running,
103 Scheduled,
104 Finished,
105 Failed,
106 Killed,
107}
108
109#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Ord, PartialOrd)]
111pub struct Experiment {
112 pub experiment_id: String,
113 pub name: String,
114 pub artifact_location: String,
115 pub lifecycle_stage: String,
116 pub last_update_time: Timestamp,
117 pub creation_time: Timestamp,
118 #[serde(default)]
119 pub tags: Vec<ExperimentTag>,
120}
121
122#[derive(Debug, Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd)]
124#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
125pub enum ViewType {
126 #[default]
127 ActiveOnly,
128 DeletedOnly,
129 All,
130}
131
132#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Ord, PartialOrd)]
134pub struct ExperimentTag {
135 pub key: String,
136 pub value: String,
137}
138
139#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Ord, PartialOrd)]
141pub struct RunTag {
142 pub key: String,
143 pub value: String,
144}
145
146#[derive(Debug, Serialize, Deserialize, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
148#[serde(transparent)]
149pub struct Timestamp(pub i64);
150
151impl Timestamp {
152 pub fn now() -> Self {
153 SystemTime::now().try_into().unwrap()
154 }
155}
156
157impl From<i64> for Timestamp {
158 fn from(i: i64) -> Self {
159 Timestamp(i)
160 }
161}
162impl From<Timestamp> for i64 {
163 fn from(ts: Timestamp) -> i64 {
164 ts.0
165 }
166}
167
168impl TryFrom<SystemTime> for Timestamp {
169 type Error = TimestampError;
170 fn try_from(value: SystemTime) -> Result<Self, Self::Error> {
171 Ok(Timestamp(if value < SystemTime::UNIX_EPOCH {
172 let millis: i128 = SystemTime::UNIX_EPOCH
173 .duration_since(value)?
174 .as_millis()
175 .try_into()?;
176 (-millis).try_into()?
177 } else {
178 value
179 .duration_since(SystemTime::UNIX_EPOCH)?
180 .as_millis()
181 .try_into()?
182 }))
183 }
184}
185impl From<Timestamp> for SystemTime {
186 fn from(value: Timestamp) -> SystemTime {
187 if value.0 < 0 {
188 SystemTime::UNIX_EPOCH - std::time::Duration::from_millis(-(value.0 as i128) as u64)
189 } else {
190 SystemTime::UNIX_EPOCH + std::time::Duration::from_millis(value.0 as u64)
191 }
192 }
193}
194
195#[derive(Debug, Error)]
196pub enum TimestampError {
197 #[error("SystemTimeError: {0}")]
198 SystemTimeError(#[from] std::time::SystemTimeError),
199 #[error("TryFromIntError: {0}")]
200 TryFromIntError(#[from] std::num::TryFromIntError),
201}
202
203#[derive(Serialize, Debug, Clone, Copy, Default)]
205pub struct CreateExperimentOptions<'a> {
206 pub artifact_location: Option<&'a str>,
207 pub tags: &'a [ExperimentTag],
208}
209
210#[derive(Serialize, Debug, Clone, Copy, Ex)]
212#[derive_ex(Default)]
213pub struct SearchExperimentsOptions<'a> {
214 pub filter: &'a str,
215 pub order_by: &'a [&'a str],
216 pub view_type: ViewType,
217}
218
219#[derive(Serialize, Debug, Clone, Copy, Default)]
221pub struct CreateRunOptions<'a> {
222 pub start_time: Option<Timestamp>,
223 pub tags: &'a [RunTag],
224}
225
226#[derive(Serialize, Debug, Clone, Copy, Ex)]
228#[derive_ex(Default)]
229pub struct SearchRunsOptions<'a> {
230 pub filter: &'a str,
231 pub run_view_type: ViewType,
232 pub order_by: &'a [&'a str],
233}
234
235#[derive(Serialize, Debug, Clone, Copy, Default)]
237pub struct UpdateRunOptions<'a> {
238 pub status: Option<RunStatus>,
239 pub end_time: Option<Timestamp>,
240 pub run_name: Option<&'a str>,
241}