#[allow(dead_code)]
pub mod testing;
use foxtive_supervisor::contracts::SupervisedTask;
use foxtive_supervisor::enums::{BackoffStrategy, RestartPolicy};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::time::Duration;
#[allow(dead_code)]
pub struct MockTask {
pub name: String,
pub fail_count: AtomicUsize,
pub max_fails: usize,
pub restart_policy: RestartPolicy,
pub backoff: BackoffStrategy,
pub priority: i32,
pub concurrency_limit: Option<usize>,
}
impl MockTask {
#[allow(dead_code)]
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
fail_count: AtomicUsize::new(0),
max_fails: 0,
restart_policy: RestartPolicy::Always,
backoff: BackoffStrategy::Fixed(Duration::from_millis(10)),
priority: 0,
concurrency_limit: None,
}
}
#[allow(dead_code)]
pub fn with_failures(mut self, max_fails: usize) -> Self {
self.max_fails = max_fails;
self
}
#[allow(dead_code)]
pub fn with_policy(mut self, policy: RestartPolicy) -> Self {
self.restart_policy = policy;
self
}
#[allow(dead_code)]
pub fn with_backoff(mut self, backoff: BackoffStrategy) -> Self {
self.backoff = backoff;
self
}
#[allow(dead_code)]
pub fn with_priority(mut self, priority: i32) -> Self {
self.priority = priority;
self
}
#[allow(dead_code)]
pub fn with_concurrency_limit(mut self, limit: usize) -> Self {
self.concurrency_limit = Some(limit);
self
}
}
#[async_trait::async_trait]
impl SupervisedTask for MockTask {
fn id(&self) -> &'static str {
Box::leak(self.name.clone().into_boxed_str())
}
fn name(&self) -> String {
self.name.clone()
}
async fn run(&self) -> foxtive_supervisor::SupervisorResult<()> {
let count = self.fail_count.fetch_add(1, Ordering::SeqCst);
if count < self.max_fails {
return Err(foxtive_supervisor::SupervisorError::from(format!("Simulated failure {}", count)));
}
Ok(())
}
fn restart_policy(&self) -> RestartPolicy {
self.restart_policy.clone()
}
fn backoff_strategy(&self) -> BackoffStrategy {
self.backoff.clone()
}
fn priority(&self) -> i32 {
self.priority
}
fn concurrency_limit(&self) -> Option<usize> {
self.concurrency_limit
}
}
#[allow(dead_code)]
pub struct PanickingTask {
pub name: String,
pub panic_count: AtomicUsize,
pub max_panics: usize,
}
#[async_trait::async_trait]
impl SupervisedTask for PanickingTask {
fn id(&self) -> &'static str {
Box::leak(self.name.clone().into_boxed_str())
}
fn name(&self) -> String {
self.name.clone()
}
async fn run(&self) -> foxtive_supervisor::SupervisorResult<()> {
let count = self.panic_count.fetch_add(1, Ordering::SeqCst);
if count < self.max_panics {
panic!("Intentional panic {}", count);
}
Ok(())
}
}
#[allow(dead_code)]
pub struct HookTrackingTask {
pub name: String,
pub setup_called: Arc<AtomicBool>,
pub cleanup_called: Arc<AtomicBool>,
pub restart_calls: Arc<AtomicUsize>,
pub error_calls: Arc<AtomicUsize>,
pub panic_calls: Arc<AtomicUsize>,
pub shutdown_called: Arc<AtomicBool>,
pub fail_once: AtomicBool,
}
impl HookTrackingTask {
#[allow(dead_code)]
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
setup_called: Arc::new(AtomicBool::new(false)),
cleanup_called: Arc::new(AtomicBool::new(false)),
restart_calls: Arc::new(AtomicUsize::new(0)),
error_calls: Arc::new(AtomicUsize::new(0)),
panic_calls: Arc::new(AtomicUsize::new(0)),
shutdown_called: Arc::new(AtomicBool::new(false)),
fail_once: AtomicBool::new(true),
}
}
}
#[async_trait::async_trait]
impl SupervisedTask for HookTrackingTask {
fn id(&self) -> &'static str {
Box::leak(self.name.clone().into_boxed_str())
}
fn name(&self) -> String {
self.name.clone()
}
fn restart_policy(&self) -> RestartPolicy {
RestartPolicy::MaxAttempts(2)
}
fn backoff_strategy(&self) -> BackoffStrategy {
BackoffStrategy::Fixed(Duration::from_millis(10))
}
async fn setup(&self) -> foxtive_supervisor::SupervisorResult<()> {
self.setup_called.store(true, Ordering::SeqCst);
Ok(())
}
async fn run(&self) -> foxtive_supervisor::SupervisorResult<()> {
if self.fail_once.swap(false, Ordering::SeqCst) {
return Err(foxtive_supervisor::SupervisorError::from("First attempt fails"));
}
Ok(())
}
async fn cleanup(&self) {
self.cleanup_called.store(true, Ordering::SeqCst);
}
async fn on_restart(&self, _attempt: usize) {
self.restart_calls.fetch_add(1, Ordering::SeqCst);
}
async fn on_error(&self, _msg: &str, _attempt: usize) {
self.error_calls.fetch_add(1, Ordering::SeqCst);
}
async fn on_panic(&self, _msg: &str, _attempt: usize) {
self.panic_calls.fetch_add(1, Ordering::SeqCst);
}
async fn on_shutdown(&self) {
self.shutdown_called.store(true, Ordering::SeqCst);
}
}