use crate::error::ExecutorError;
use crate::fault::{ExecutorFaultReason, FaultReason};
use crate::stats::CycleObservation;
use crate::task_id::TaskId;
#[derive(Clone, Debug, Default)]
#[non_exhaustive]
pub struct UserEvent {
pub kind: u32,
pub int_data: i64,
pub string_data: Option<String>,
}
impl UserEvent {
#[must_use]
pub const fn new(kind: u32, int_data: i64) -> Self {
Self {
kind,
int_data,
string_data: None,
}
}
#[must_use]
pub fn with_string(mut self, s: impl Into<String>) -> Self {
self.string_data = Some(s.into());
self
}
}
pub trait Observer: Send + Sync {
fn on_executor_up(&self) {}
fn on_executor_down(&self) {}
fn on_executor_error(&self, _e: &ExecutorError) {}
fn on_app_start(&self, _task: TaskId, _app: u32, _instance: Option<u32>) {}
fn on_app_stop(&self, _task: TaskId) {}
fn on_app_error(&self, _task: TaskId, _e: &(dyn std::error::Error + 'static)) {}
fn on_send_event(&self, _task: TaskId, _ev: UserEvent) {}
fn on_task_fault(&self, _task: TaskId, _reason: FaultReason) {}
fn on_task_clear(&self, _task: TaskId) {}
fn on_executor_fault(&self, _reason: ExecutorFaultReason) {}
fn on_executor_clear(&self) {}
fn on_cycle_stats(&self, _obs: &CycleObservation) {}
}
pub struct NoopObserver;
impl Observer for NoopObserver {}
#[cfg(test)]
mod cycle_stats_hook_tests {
use super::*;
use crate::TaskId;
use crate::stats::CycleObservation;
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
struct CountingObs(Arc<AtomicU64>);
impl Observer for CountingObs {
fn on_cycle_stats(&self, _: &CycleObservation) {
self.0.fetch_add(1, Ordering::Relaxed);
}
}
fn sample_obs() -> CycleObservation {
CycleObservation {
cycle_index: 0,
task_id: TaskId::from("t"),
task_index: 0,
faulted: false,
period_ns: 0,
pre_ns: 0,
actual_period_ns: None,
jitter_ns: None,
lateness_ns: None,
skipped_slots: 0,
took_ns: None,
}
}
#[test]
fn default_on_cycle_stats_is_noop() {
let noop = NoopObserver;
noop.on_cycle_stats(&sample_obs()); }
#[test]
fn overridden_on_cycle_stats_fires() {
let n = Arc::new(AtomicU64::new(0));
let c = CountingObs(Arc::clone(&n));
c.on_cycle_stats(&sample_obs());
assert_eq!(n.load(Ordering::Relaxed), 1);
}
}