git_internal/internal/object/
task_event.rs1use std::fmt;
25
26use serde::{Deserialize, Serialize};
27use uuid::Uuid;
28
29use crate::{
30 errors::GitError,
31 hash::ObjectHash,
32 internal::object::{
33 ObjectTrait,
34 types::{ActorRef, Header, ObjectType},
35 },
36};
37
38#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
39#[serde(rename_all = "snake_case")]
40pub enum TaskEventKind {
41 Created,
42 Running,
43 Blocked,
44 Done,
45 Failed,
46 Cancelled,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
51#[serde(deny_unknown_fields)]
52pub struct TaskEvent {
53 #[serde(flatten)]
56 header: Header,
57 task_id: Uuid,
59 kind: TaskEventKind,
61 #[serde(default, skip_serializing_if = "Option::is_none")]
63 reason: Option<String>,
64 #[serde(default, skip_serializing_if = "Option::is_none")]
66 run_id: Option<Uuid>,
67}
68
69impl TaskEvent {
70 pub fn new(created_by: ActorRef, task_id: Uuid, kind: TaskEventKind) -> Result<Self, String> {
72 Ok(Self {
73 header: Header::new(ObjectType::TaskEvent, created_by)?,
74 task_id,
75 kind,
76 reason: None,
77 run_id: None,
78 })
79 }
80
81 pub fn header(&self) -> &Header {
83 &self.header
84 }
85
86 pub fn task_id(&self) -> Uuid {
88 self.task_id
89 }
90
91 pub fn kind(&self) -> &TaskEventKind {
93 &self.kind
94 }
95
96 pub fn reason(&self) -> Option<&str> {
98 self.reason.as_deref()
99 }
100
101 pub fn run_id(&self) -> Option<Uuid> {
103 self.run_id
104 }
105
106 pub fn set_reason(&mut self, reason: Option<String>) {
108 self.reason = reason;
109 }
110
111 pub fn set_run_id(&mut self, run_id: Option<Uuid>) {
113 self.run_id = run_id;
114 }
115}
116
117impl fmt::Display for TaskEvent {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 write!(f, "TaskEvent: {}", self.header.object_id())
120 }
121}
122
123impl ObjectTrait for TaskEvent {
124 fn from_bytes(data: &[u8], _hash: ObjectHash) -> Result<Self, GitError>
125 where
126 Self: Sized,
127 {
128 serde_json::from_slice(data).map_err(|e| GitError::InvalidObjectInfo(e.to_string()))
129 }
130
131 fn get_type(&self) -> ObjectType {
132 ObjectType::TaskEvent
133 }
134
135 fn get_size(&self) -> usize {
136 match serde_json::to_vec(self) {
137 Ok(v) => v.len(),
138 Err(e) => {
139 tracing::warn!("failed to compute TaskEvent size: {}", e);
140 0
141 }
142 }
143 }
144
145 fn to_data(&self) -> Result<Vec<u8>, GitError> {
146 serde_json::to_vec(self).map_err(|e| GitError::InvalidObjectInfo(e.to_string()))
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
159 fn test_task_event_fields() {
160 let actor = ActorRef::agent("planner").expect("actor");
161 let mut event =
162 TaskEvent::new(actor, Uuid::from_u128(0x1), TaskEventKind::Running).expect("event");
163 let run_id = Uuid::from_u128(0x2);
164 event.set_reason(Some("agent started".to_string()));
165 event.set_run_id(Some(run_id));
166
167 assert_eq!(event.kind(), &TaskEventKind::Running);
168 assert_eq!(event.reason(), Some("agent started"));
169 assert_eq!(event.run_id(), Some(run_id));
170 }
171}