From ac4dcbadc1d63b0116fe5b55f529b719f27b1ba4 Mon Sep 17 00:00:00 2001 From: Konstantin Shabanov Date: Sun, 2 Oct 2022 23:50:23 +0600 Subject: [PATCH] chore: Drop trigger-new leftovers Refs: #763. Signed-off-by: Konstantin Shabanov --- crates/trigger-new/src/lib.rs | 282 ---------------------------------- 1 file changed, 282 deletions(-) delete mode 100644 crates/trigger-new/src/lib.rs diff --git a/crates/trigger-new/src/lib.rs b/crates/trigger-new/src/lib.rs deleted file mode 100644 index 979fc66bbc..0000000000 --- a/crates/trigger-new/src/lib.rs +++ /dev/null @@ -1,282 +0,0 @@ -pub mod cli; -mod loader; -pub mod locked; -mod stdio; - -use std::{ - collections::HashMap, - marker::PhantomData, - path::{Path, PathBuf}, -}; - -use anyhow::{Context, Result}; -pub use async_trait::async_trait; -use serde::de::DeserializeOwned; - -use spin_app::{App, AppLoader, AppTrigger, Loader, OwnedApp}; -use spin_config::{provider::env::EnvProvider, Provider}; -use spin_core::{Config, Engine, EngineBuilder, Instance, InstancePre, Store, StoreBuilder}; - -use stdio::{ComponentStdioWriter, FollowComponents}; - -const SPIN_HOME: &str = ".spin"; -const SPIN_CONFIG_ENV_PREFIX: &str = "SPIN_APP"; - -#[async_trait] -pub trait TriggerExecutor: Sized { - const TRIGGER_TYPE: &'static str; - type RuntimeData: Default + Send + Sync + 'static; - type TriggerConfig; - type RunConfig; - - /// Create a new trigger executor. - fn new(engine: TriggerAppEngine) -> Result; - - /// Run the trigger executor. - async fn run(self, config: Self::RunConfig) -> Result<()>; - - /// Make changes to the ExecutionContext using the given Builder. - fn configure_engine(_builder: &mut EngineBuilder) -> Result<()> { - Ok(()) - } -} - -pub struct TriggerExecutorBuilder { - loader: AppLoader, - config: Config, - log_dir: Option, - follow_components: FollowComponents, - disable_default_host_components: bool, - _phantom: PhantomData, -} - -impl TriggerExecutorBuilder { - /// Create a new TriggerExecutorBuilder with the given Application. - pub fn new(loader: impl Loader + Send + Sync + 'static) -> Self { - Self { - loader: AppLoader::new(loader), - config: Default::default(), - log_dir: None, - follow_components: Default::default(), - disable_default_host_components: false, - _phantom: PhantomData, - } - } - - /// !!!Warning!!! Using a custom Wasmtime Config is entirely unsupported; - /// many configurations are likely to cause errors or unexpected behavior. - #[doc(hidden)] - pub fn wasmtime_config_mut(&mut self) -> &mut spin_core::wasmtime::Config { - self.config.wasmtime_config() - } - - pub fn log_dir(&mut self, log_dir: PathBuf) -> &mut Self { - self.log_dir = Some(log_dir); - self - } - - pub fn follow_components(&mut self, follow_components: FollowComponents) -> &mut Self { - self.follow_components = follow_components; - self - } - - pub fn disable_default_host_components(&mut self) -> &mut Self { - self.disable_default_host_components = true; - self - } - - pub async fn build(mut self, app_uri: String) -> Result - where - Executor::TriggerConfig: DeserializeOwned, - { - let engine = { - let mut builder = Engine::builder(&self.config)?; - - if !self.disable_default_host_components { - builder.add_host_component(outbound_redis::OutboundRedis::default())?; - builder.add_host_component(outbound_pg::OutboundPg::default())?; - self.loader.add_dynamic_host_component( - &mut builder, - outbound_http::OutboundHttpComponent, - )?; - self.loader.add_dynamic_host_component( - &mut builder, - spin_config::ConfigHostComponent::new(self.default_config_providers(&app_uri)), - )?; - } - - Executor::configure_engine(&mut builder)?; - builder.build() - }; - - let app = self.loader.load_owned_app(app_uri).await?; - let app_name = app.require_metadata("name")?; - - let log_dir = { - let sanitized_app = sanitize_filename::sanitize(&app_name); - let parent_dir = match dirs::home_dir() { - Some(home) => home.join(SPIN_HOME), - None => PathBuf::new(), // "./" - }; - parent_dir.join(sanitized_app).join("logs") - }; - std::fs::create_dir_all(&log_dir)?; - - // Run trigger executor - Executor::new( - TriggerAppEngine::new(engine, app_name, app, log_dir, self.follow_components).await?, - ) - } - - pub fn default_config_providers(&self, app_uri: &str) -> Vec> { - // EnvProvider - let dotenv_path = app_uri - .strip_prefix("file://") - .and_then(|path| Path::new(path).parent()) - .unwrap_or_else(|| Path::new(".")) - .join(".env"); - vec![Box::new(EnvProvider::new( - SPIN_CONFIG_ENV_PREFIX, - Some(dotenv_path), - ))] - } -} - -/// Execution context for a TriggerExecutor executing a particular App. -pub struct TriggerAppEngine { - /// Engine to be used with this executor. - pub engine: Engine, - /// Name of the app for e.g. logging. - pub app_name: String, - // An owned wrapper of the App. - app: OwnedApp, - // Log directory - log_dir: PathBuf, - // Component stdio follow config - follow_components: FollowComponents, - // Trigger configs for this trigger type, with order matching `app.triggers_with_type(Executor::TRIGGER_TYPE)` - trigger_configs: Vec, - // Map of {Component ID -> InstancePre} for each component. - component_instance_pres: HashMap>, -} - -impl TriggerAppEngine { - /// Returns a new TriggerAppEngine. May return an error if trigger config validation or - /// component pre-instantiation fails. - pub async fn new( - engine: Engine, - app_name: String, - app: OwnedApp, - log_dir: PathBuf, - follow_components: FollowComponents, - ) -> Result - where - ::TriggerConfig: DeserializeOwned, - { - let trigger_configs = app - .triggers_with_type(Executor::TRIGGER_TYPE) - .map(|trigger| { - trigger.typed_config().with_context(|| { - format!("invalid trigger configuration for {:?}", trigger.id()) - }) - }) - .collect::>()?; - - let mut component_instance_pres = HashMap::default(); - for component in app.components() { - let module = component.load_module(&engine).await?; - let instance_pre = engine.instantiate_pre(&module)?; - component_instance_pres.insert(component.id().to_string(), instance_pre); - } - - Ok(Self { - engine, - app_name, - app, - log_dir, - follow_components, - trigger_configs, - component_instance_pres, - }) - } - - /// Returns a reference to the App. - pub fn app(&self) -> &App { - &self.app - } - - /// Returns AppTriggers and typed TriggerConfigs for this executor type. - pub fn trigger_configs(&self) -> impl Iterator { - self.app - .triggers_with_type(Executor::TRIGGER_TYPE) - .zip(&self.trigger_configs) - } - - /// Returns a new StoreBuilder for the given component ID. - pub fn store_builder(&self, component_id: &str) -> Result { - let mut builder = self.engine.store_builder(); - - // Set up stdio logging - builder.stdout_pipe(self.component_stdio_writer(component_id, "stdout")?); - builder.stderr_pipe(self.component_stdio_writer(component_id, "stderr")?); - - Ok(builder) - } - - fn component_stdio_writer( - &self, - component_id: &str, - log_suffix: &str, - ) -> Result { - let sanitized_component_id = sanitize_filename::sanitize(component_id); - // e.g. - let log_path = self - .log_dir - .join(format!("{sanitized_component_id}_{log_suffix}.txt")); - let follow = self.follow_components.should_follow(component_id); - ComponentStdioWriter::new(&log_path, follow) - .with_context(|| format!("Failed to open log file {log_path:?}")) - } - - /// Returns a new Store and Instance for the given component ID. - pub async fn prepare_instance( - &self, - component_id: &str, - ) -> Result<(Instance, Store)> { - let store_builder = self.store_builder(component_id)?; - self.prepare_instance_with_store(component_id, store_builder) - .await - } - - /// Returns a new Store and Instance for the given component ID and StoreBuilder. - pub async fn prepare_instance_with_store( - &self, - component_id: &str, - mut store_builder: StoreBuilder, - ) -> Result<(Instance, Store)> { - // Look up AppComponent - let component = self.app.get_component(component_id).with_context(|| { - format!( - "app {:?} has no component {:?}", - self.app_name, component_id - ) - })?; - - // Build Store - component.apply_store_config(&mut store_builder).await?; - let mut store = store_builder.build()?; - - // Instantiate - let instance = self.component_instance_pres[component_id] - .instantiate_async(&mut store) - .await - .with_context(|| { - format!( - "app {:?} component {:?} instantiation failed", - self.app_name, component_id - ) - })?; - - Ok((instance, store)) - } -}