oura 2.2.0

The tail of Cardano
Documentation
use gasket::framework::*;
use serde::Deserialize;
use tracing::info;

use crate::framework::*;

use self::eval::{MatchOutcome, Predicate, StringOrStruct};

pub mod eval;

#[derive(Stage)]
#[stage(name = "select", unit = "ChainEvent", worker = "Worker")]
pub struct Stage {
    predicate: Predicate,
    skip_uncertain: bool,

    pub input: FilterInputPort,
    pub output: FilterOutputPort,

    #[metric]
    ops_count: gasket::metrics::Counter,
}

#[derive(Default)]
pub struct Worker;

#[async_trait::async_trait(?Send)]
impl gasket::framework::Worker<Stage> for Worker {
    async fn bootstrap(_: &Stage) -> Result<Self, WorkerError> {
        Ok(Default::default())
    }

    async fn schedule(
        &mut self,
        stage: &mut Stage,
    ) -> Result<WorkSchedule<ChainEvent>, WorkerError> {
        let msg = stage.input.recv().await.or_panic()?;

        Ok(WorkSchedule::Unit(msg.payload))
    }

    async fn execute(&mut self, unit: &ChainEvent, stage: &mut Stage) -> Result<(), WorkerError> {
        let is_match = match unit {
            ChainEvent::Apply(_, r) => eval::eval(r, &stage.predicate),
            ChainEvent::Undo(_, r) => eval::eval(r, &stage.predicate),
            ChainEvent::Reset(_) => MatchOutcome::Positive,
        };

        match is_match {
            MatchOutcome::Positive => stage.output.send(unit.clone().into()).await.or_panic()?,
            MatchOutcome::Negative => (),
            MatchOutcome::Uncertain => {
                if !stage.skip_uncertain {
                    return Err(WorkerError::Panic);
                }
            }
        };

        stage.ops_count.inc(1);

        Ok(())
    }
}

#[derive(Deserialize)]
pub struct Config {
    pub predicate: StringOrStruct<Predicate>,
    pub skip_uncertain: bool,
}

impl Config {
    pub fn bootstrapper(self, _ctx: &Context) -> Result<Stage, Error> {
        info!(predicate = ?self.predicate, "selection filter predicate");

        let stage = Stage {
            predicate: self.predicate.unwrap(),
            skip_uncertain: self.skip_uncertain,
            ops_count: Default::default(),
            input: Default::default(),
            output: Default::default(),
        };

        Ok(stage)
    }
}