use indexmap::IndexMap;
use nautilus_core::UnixNanos;
pub use nautilus_system::{RegisteredComponents, event_store::RunId};
use serde::{Deserialize, Serialize};
use crate::wire;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum RunStatus {
Running,
Ended,
CrashedRecovered,
Quarantined,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct RunManifest {
pub run_id: RunId,
pub parent_run_id: Option<RunId>,
pub instance_id: String,
pub binary_hash: String,
pub schema_version: u32,
pub crate_versions: String,
pub feature_flags: Vec<String>,
pub adapter_versions: IndexMap<String, String>,
pub config_hash: String,
pub registered_components: RegisteredComponents,
pub seed: Option<u64>,
#[serde(with = "wire::nanos_as_u64")]
pub start_ts_init: UnixNanos,
#[serde(with = "wire::opt_nanos_as_u64")]
pub end_ts_init: Option<UnixNanos>,
pub high_watermark: u64,
pub status: RunStatus,
}
impl RunManifest {
#[must_use]
pub const fn is_sealed(&self) -> bool {
!matches!(self.status, RunStatus::Running)
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
fn manifest_with(status: RunStatus) -> RunManifest {
RunManifest {
run_id: "1700000000-abcd1234".to_string(),
parent_run_id: None,
instance_id: "trader-001".to_string(),
binary_hash: "deadbeef".to_string(),
schema_version: 1,
crate_versions: "feedface".to_string(),
feature_flags: vec!["live".to_string()],
adapter_versions: IndexMap::new(),
config_hash: "cafebabe".to_string(),
registered_components: RegisteredComponents::default(),
seed: None,
start_ts_init: UnixNanos::from(0),
end_ts_init: None,
high_watermark: 0,
status,
}
}
#[rstest]
#[case(RunStatus::Running, false)]
#[case(RunStatus::Ended, true)]
#[case(RunStatus::CrashedRecovered, true)]
#[case(RunStatus::Quarantined, true)]
fn is_sealed_matches_status(#[case] status: RunStatus, #[case] expected: bool) {
assert_eq!(manifest_with(status).is_sealed(), expected);
}
}