use crate::error::{MediaError, StageError};
use crate::id::{FeedId, StageId};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum DecodeOutcome {
Hardware,
Software,
Unknown,
}
impl std::fmt::Display for DecodeOutcome {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Hardware => f.write_str("Hardware"),
Self::Software => f.write_str("Software"),
Self::Unknown => f.write_str("Unknown"),
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum DecodePreference {
#[default]
Auto,
CpuOnly,
PreferHardware,
RequireHardware,
}
impl std::fmt::Display for DecodePreference {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Auto => f.write_str("Auto"),
Self::CpuOnly => f.write_str("CpuOnly"),
Self::PreferHardware => f.write_str("PreferHardware"),
Self::RequireHardware => f.write_str("RequireHardware"),
}
}
}
#[derive(Debug, Clone)]
pub enum HealthEvent {
SourceConnected { feed_id: FeedId },
SourceDisconnected { feed_id: FeedId, reason: MediaError },
SourceReconnecting { feed_id: FeedId, attempt: u32 },
InsecureRtspSource {
feed_id: FeedId,
redacted_url: String,
},
StageError {
feed_id: FeedId,
stage_id: StageId,
error: StageError,
},
StagePanic { feed_id: FeedId, stage_id: StageId },
FeedRestarting { feed_id: FeedId, restart_count: u32 },
FeedStopped { feed_id: FeedId, reason: StopReason },
BackpressureDrop {
feed_id: FeedId,
frames_dropped: u64,
},
FrameLag {
feed_id: FeedId,
frame_age_ms: u64,
frames_lagged: u64,
},
ViewEpochChanged {
feed_id: FeedId,
epoch: u64,
},
ViewDegraded {
feed_id: FeedId,
stability_score: f32,
},
ViewCompensationApplied { feed_id: FeedId, epoch: u64 },
OutputLagged {
messages_lost: u64,
},
SourceEos { feed_id: FeedId },
DecodeDecision {
feed_id: FeedId,
outcome: DecodeOutcome,
preference: DecodePreference,
fallback_active: bool,
fallback_reason: Option<String>,
detail: String,
},
SinkPanic { feed_id: FeedId },
SinkTimeout { feed_id: FeedId },
SinkBackpressure {
feed_id: FeedId,
outputs_dropped: u64,
},
TrackAdmissionRejected {
feed_id: FeedId,
rejected_count: u32,
},
BatchError {
processor_id: StageId,
batch_size: u32,
error: StageError,
},
BatchSubmissionRejected {
feed_id: FeedId,
processor_id: StageId,
dropped_count: u64,
},
BatchTimeout {
feed_id: FeedId,
processor_id: StageId,
timed_out_count: u64,
},
BatchInFlightExceeded {
feed_id: FeedId,
processor_id: StageId,
rejected_count: u64,
},
ResidencyDowngrade {
feed_id: FeedId,
requested: String,
effective: String,
},
}
#[derive(Debug, Clone)]
pub enum StopReason {
UserRequested,
RestartLimitExceeded { restart_count: u32 },
EndOfStream,
Fatal { detail: String },
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn decode_outcome_display() {
assert_eq!(DecodeOutcome::Hardware.to_string(), "Hardware");
assert_eq!(DecodeOutcome::Software.to_string(), "Software");
assert_eq!(DecodeOutcome::Unknown.to_string(), "Unknown");
}
#[test]
fn decode_preference_display() {
assert_eq!(DecodePreference::Auto.to_string(), "Auto");
assert_eq!(DecodePreference::CpuOnly.to_string(), "CpuOnly");
assert_eq!(
DecodePreference::PreferHardware.to_string(),
"PreferHardware"
);
assert_eq!(
DecodePreference::RequireHardware.to_string(),
"RequireHardware"
);
}
#[test]
fn stop_reason_variants() {
let user = StopReason::UserRequested;
let restart = StopReason::RestartLimitExceeded { restart_count: 3 };
let eos = StopReason::EndOfStream;
let fatal = StopReason::Fatal {
detail: "test".into(),
};
let _ = format!("{user:?}");
let _ = format!("{restart:?}");
let _ = format!("{eos:?}");
let _ = format!("{fatal:?}");
}
#[test]
fn health_event_is_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<HealthEvent>();
}
}