use std::fmt;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::{
errors::GitError,
hash::ObjectHash,
internal::object::{
ObjectTrait,
types::{ActorRef, Header, ObjectType},
},
};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum TaskEventKind {
Created,
Running,
Blocked,
Done,
Failed,
Cancelled,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct TaskEvent {
#[serde(flatten)]
header: Header,
task_id: Uuid,
kind: TaskEventKind,
#[serde(default, skip_serializing_if = "Option::is_none")]
reason: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
run_id: Option<Uuid>,
}
impl TaskEvent {
pub fn new(created_by: ActorRef, task_id: Uuid, kind: TaskEventKind) -> Result<Self, String> {
Ok(Self {
header: Header::new(ObjectType::TaskEvent, created_by)?,
task_id,
kind,
reason: None,
run_id: None,
})
}
pub fn header(&self) -> &Header {
&self.header
}
pub fn task_id(&self) -> Uuid {
self.task_id
}
pub fn kind(&self) -> &TaskEventKind {
&self.kind
}
pub fn reason(&self) -> Option<&str> {
self.reason.as_deref()
}
pub fn run_id(&self) -> Option<Uuid> {
self.run_id
}
pub fn set_reason(&mut self, reason: Option<String>) {
self.reason = reason;
}
pub fn set_run_id(&mut self, run_id: Option<Uuid>) {
self.run_id = run_id;
}
}
impl fmt::Display for TaskEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "TaskEvent: {}", self.header.object_id())
}
}
impl ObjectTrait for TaskEvent {
fn from_bytes(data: &[u8], _hash: ObjectHash) -> Result<Self, GitError>
where
Self: Sized,
{
serde_json::from_slice(data).map_err(|e| GitError::InvalidObjectInfo(e.to_string()))
}
fn get_type(&self) -> ObjectType {
ObjectType::TaskEvent
}
fn get_size(&self) -> usize {
match serde_json::to_vec(self) {
Ok(v) => v.len(),
Err(e) => {
tracing::warn!("failed to compute TaskEvent size: {}", e);
0
}
}
}
fn to_data(&self) -> Result<Vec<u8>, GitError> {
serde_json::to_vec(self).map_err(|e| GitError::InvalidObjectInfo(e.to_string()))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_task_event_fields() {
let actor = ActorRef::agent("planner").expect("actor");
let mut event =
TaskEvent::new(actor, Uuid::from_u128(0x1), TaskEventKind::Running).expect("event");
let run_id = Uuid::from_u128(0x2);
event.set_reason(Some("agent started".to_string()));
event.set_run_id(Some(run_id));
assert_eq!(event.kind(), &TaskEventKind::Running);
assert_eq!(event.reason(), Some("agent started"));
assert_eq!(event.run_id(), Some(run_id));
}
}