use super::{processed::ProcessedHeight, tracker::ProgressTracker};
use commonware_cryptography::PublicKey;
use std::{future::Future, pin::Pin};
pub trait ExitCondition<P: PublicKey, S>: Send + Sync {
fn name(&self) -> &str;
fn requires_polling(&self) -> bool {
false
}
fn reached<'a>(
&'a self,
tracker: &'a ProgressTracker<P>,
states: &'a [&'a S],
target_count: usize,
) -> Pin<Box<dyn Future<Output = Result<bool, String>> + Send + 'a>>;
}
#[derive(Clone)]
pub struct MinimumFinalizations {
required: u64,
}
impl MinimumFinalizations {
pub const fn new(required: u64) -> Self {
Self { required }
}
}
impl<P: PublicKey, S> ExitCondition<P, S> for MinimumFinalizations {
fn name(&self) -> &str {
"minimum_finalizations"
}
fn reached<'a>(
&'a self,
tracker: &'a ProgressTracker<P>,
_states: &'a [&'a S],
target_count: usize,
) -> Pin<Box<dyn Future<Output = Result<bool, String>> + Send + 'a>> {
Box::pin(async move { Ok(tracker.all_reached(target_count, self.required)) })
}
}
#[derive(Clone)]
pub struct ProcessedHeightAtLeast {
required: u64,
}
impl ProcessedHeightAtLeast {
pub const fn new(required: u64) -> Self {
Self { required }
}
}
impl<P: PublicKey, S: ProcessedHeight> ExitCondition<P, S> for ProcessedHeightAtLeast {
fn name(&self) -> &str {
"processed_height_at_least"
}
fn requires_polling(&self) -> bool {
true
}
fn reached<'a>(
&'a self,
_tracker: &'a ProgressTracker<P>,
states: &'a [&'a S],
target_count: usize,
) -> Pin<Box<dyn Future<Output = Result<bool, String>> + Send + 'a>> {
Box::pin(async move {
let mut reached = 0usize;
for state in states {
if state.processed_height().await >= self.required {
reached += 1;
}
}
Ok(reached >= target_count)
})
}
}