git_internal/internal/object/
run_event.rs1use std::fmt;
27
28use serde::{Deserialize, Serialize};
29use uuid::Uuid;
30
31use crate::{
32 errors::GitError,
33 hash::ObjectHash,
34 internal::object::{
35 ObjectTrait,
36 types::{ActorRef, Header, ObjectType},
37 },
38};
39
40#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
41#[serde(rename_all = "snake_case")]
42pub enum RunEventKind {
43 Created,
44 Patching,
45 Validating,
46 Completed,
47 Failed,
48 Checkpointed,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
53#[serde(deny_unknown_fields)]
54pub struct RunEvent {
55 #[serde(flatten)]
58 header: Header,
59 run_id: Uuid,
61 kind: RunEventKind,
63 #[serde(default, skip_serializing_if = "Option::is_none")]
65 reason: Option<String>,
66 #[serde(default, skip_serializing_if = "Option::is_none")]
68 error: Option<String>,
69 #[serde(default, skip_serializing_if = "Option::is_none")]
71 metrics: Option<serde_json::Value>,
72 #[serde(default, skip_serializing_if = "Option::is_none")]
74 patchset_id: Option<Uuid>,
75}
76
77impl RunEvent {
78 pub fn new(created_by: ActorRef, run_id: Uuid, kind: RunEventKind) -> Result<Self, String> {
80 Ok(Self {
81 header: Header::new(ObjectType::RunEvent, created_by)?,
82 run_id,
83 kind,
84 reason: None,
85 error: None,
86 metrics: None,
87 patchset_id: None,
88 })
89 }
90
91 pub fn header(&self) -> &Header {
93 &self.header
94 }
95
96 pub fn run_id(&self) -> Uuid {
98 self.run_id
99 }
100
101 pub fn kind(&self) -> &RunEventKind {
103 &self.kind
104 }
105
106 pub fn reason(&self) -> Option<&str> {
108 self.reason.as_deref()
109 }
110
111 pub fn error(&self) -> Option<&str> {
113 self.error.as_deref()
114 }
115
116 pub fn metrics(&self) -> Option<&serde_json::Value> {
118 self.metrics.as_ref()
119 }
120
121 pub fn patchset_id(&self) -> Option<Uuid> {
123 self.patchset_id
124 }
125
126 pub fn set_reason(&mut self, reason: Option<String>) {
128 self.reason = reason;
129 }
130
131 pub fn set_error(&mut self, error: Option<String>) {
133 self.error = error;
134 }
135
136 pub fn set_metrics(&mut self, metrics: Option<serde_json::Value>) {
138 self.metrics = metrics;
139 }
140
141 pub fn set_patchset_id(&mut self, patchset_id: Option<Uuid>) {
143 self.patchset_id = patchset_id;
144 }
145}
146
147impl fmt::Display for RunEvent {
148 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149 write!(f, "RunEvent: {}", self.header.object_id())
150 }
151}
152
153impl ObjectTrait for RunEvent {
154 fn from_bytes(data: &[u8], _hash: ObjectHash) -> Result<Self, GitError>
155 where
156 Self: Sized,
157 {
158 serde_json::from_slice(data).map_err(|e| GitError::InvalidObjectInfo(e.to_string()))
159 }
160
161 fn get_type(&self) -> ObjectType {
162 ObjectType::RunEvent
163 }
164
165 fn get_size(&self) -> usize {
166 match serde_json::to_vec(self) {
167 Ok(v) => v.len(),
168 Err(e) => {
169 tracing::warn!("failed to compute RunEvent size: {}", e);
170 0
171 }
172 }
173 }
174
175 fn to_data(&self) -> Result<Vec<u8>, GitError> {
176 serde_json::to_vec(self).map_err(|e| GitError::InvalidObjectInfo(e.to_string()))
177 }
178}
179
180#[cfg(test)]
181mod tests {
182 use super::*;
183
184 #[test]
189 fn test_run_event_fields() {
190 let actor = ActorRef::agent("planner").expect("actor");
191 let mut event =
192 RunEvent::new(actor, Uuid::from_u128(0x1), RunEventKind::Failed).expect("event");
193 let patchset_id = Uuid::from_u128(0x2);
194 event.set_reason(Some("validation failed".to_string()));
195 event.set_error(Some("cargo test failed".to_string()));
196 event.set_metrics(Some(serde_json::json!({"duration_ms": 1200})));
197 event.set_patchset_id(Some(patchset_id));
198
199 assert_eq!(event.kind(), &RunEventKind::Failed);
200 assert_eq!(event.reason(), Some("validation failed"));
201 assert_eq!(event.error(), Some("cargo test failed"));
202 assert_eq!(event.patchset_id(), Some(patchset_id));
203 }
204}