use crate::*;
use serde::{Deserialize, Serialize};
use std::collections::BTreeSet;
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ExecutionRecord {
pub status: WorkStatus,
#[serde(default)]
pub reported_progress_percent: u8,
pub artifact_ids: BTreeSet<ArtifactId>,
pub owner: Option<ActorId>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub handoffs: Vec<crate::Handoff>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub releases: Vec<crate::ClaimRelease>,
#[serde(default, skip_serializing_if = "crate::ExecutionEvents::is_empty")]
pub events: crate::ExecutionEvents,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_rejection: Option<ReviewRejection>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub attempts: Vec<crate::SubmissionAttempt>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub basis: Vec<crate::DependencyBasis>,
pub block_reason: Option<String>,
}
impl ExecutionRecord {
#[must_use]
pub fn latest_recorded_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
let events = [
self.events.claimed_at,
self.events.started_at,
self.events.submitted_at,
self.events.verified_at,
self.last_rejection.as_ref().map(|r| r.at),
];
let reviews = self.attempts.iter().flat_map(|a| {
let closed = match &a.outcome {
AttemptOutcome::Pending => None,
AttemptOutcome::Rejected { at, .. } | AttemptOutcome::Verified { at, .. } => {
Some(*at)
}
};
[Some(a.submitted_at), closed]
});
events
.into_iter()
.chain(reviews)
.flatten()
.chain(self.handoffs.iter().map(|h| h.at))
.chain(self.releases.iter().map(|r| r.at))
.chain(self.basis.iter().map(|b| b.recorded_at))
.max()
}
}
#[cfg(test)]
mod tests;