use super::{Add, AddGeneric, AddResult, AddableResource, Runnable, SymbolRunner}; use crate::{ImplementationBuilder, ResourceLocator}; use async_trait::async_trait; use slog::{debug, o, trace, Logger}; use std::fmt::Debug; use std::marker::PhantomData; use std::rc::{Rc, Weak}; #[derive(Debug)] pub struct Realizer { symbol_runner: Rc, outer: Weak, phantom: PhantomData<(L, B)>, } impl Realizer { pub fn new(symbol_runner: Rc, outer: Weak) -> Self { Self { symbol_runner, outer, phantom: PhantomData::default(), } } } #[async_trait(?Send)] impl Add for Realizer where R: AddableResource, SR: SymbolRunner, L: ResourceLocator, B: ImplementationBuilder, >::Implementation: Runnable + Debug, S: AddGeneric + AddGeneric<>::Prerequisites>, { async fn add(&self, logger: &Rc, resource: Rc, force_run: bool) -> AddResult { let setup = self.outer.upgrade().unwrap(); let logger = Rc::new(logger.new(o!("resource" => format!("{resource:?}")))); trace!(logger, "(force_run is {})", force_run); let (location, location_prereqs) = L::locate(&resource); trace!(logger, "Adding location prereqs ..."); let (_, location_prereqs_did_run) = (*setup) .add_generic(&logger, location_prereqs, false) .await?; trace!( logger, "Location prereqs did_run: {}", location_prereqs_did_run ); trace!(logger, "Adding implementation prereqs ..."); let (prereqs, prereqs_did_run) = (*setup) .add_generic(&logger, B::prerequisites(&resource), false) .await?; trace!( logger, "Implementation prereqs did_run: {}", prereqs_did_run ); trace!(logger, "Running implementation ..."); let implementation = B::create(&resource, &location, prereqs); let did_run = implementation .run( &*self.symbol_runner, &logger, force_run || location_prereqs_did_run || prereqs_did_run, ) .await?; debug!(logger, "done."); Ok((location, did_run)) } }