Skip to main content

spin_runtime_factors/
build.rs

1use std::path::PathBuf;
2
3use super::{TriggerAppArgs, TriggerFactors, TriggerFactorsRuntimeConfig};
4
5use anyhow::Context as _;
6use spin_factors_executor::FactorsExecutor;
7use spin_runtime_config::ResolvedRuntimeConfig;
8use spin_trigger::cli::{
9    FactorsConfig, InitialKvSetterHook, KeyValueDefaultStoreSummaryHook, MaxInstanceMemoryHook,
10    RuntimeFactorsBuilder, SqlStatementExecutorHook, SqliteDefaultStoreSummaryHook,
11    StdioLoggingExecutorHooks, VariablesValidatorHook,
12};
13use spin_variables_static::StaticVariablesProvider;
14
15/// A [`RuntimeFactorsBuilder`] for [`TriggerFactors`].
16pub struct FactorsBuilder;
17
18impl RuntimeFactorsBuilder for FactorsBuilder {
19    type CliArgs = TriggerAppArgs;
20    type Factors = TriggerFactors;
21    type RuntimeConfig = ResolvedRuntimeConfig<TriggerFactorsRuntimeConfig>;
22
23    fn build(
24        config: &FactorsConfig,
25        args: &Self::CliArgs,
26    ) -> anyhow::Result<(Self::Factors, Self::RuntimeConfig)> {
27        let mut runtime_config = ResolvedRuntimeConfig::<TriggerFactorsRuntimeConfig>::from_file(
28            config.runtime_config_file.clone().as_deref(),
29            config.local_app_dir.clone().map(PathBuf::from),
30            config.state_dir.clone(),
31            config.log_dir.clone(),
32        )?;
33
34        let cli_static_variables = args.get_variables()?.clone();
35        let cli_static_variables_provider = StaticVariablesProvider::new(cli_static_variables);
36
37        // Insert the parsed static variables provided via cli arguments
38        // into the set of variable providers with highest precedence.
39        runtime_config
40            .runtime_config
41            .variables
42            .as_mut()
43            .unwrap()
44            .providers
45            .insert(0, Box::new(cli_static_variables_provider));
46
47        runtime_config.summarize(config.runtime_config_file.as_deref());
48
49        // This is a hack b/c we know the version of this crate will be the same as the version of Spin
50        let spin_version = env!("CARGO_PKG_VERSION");
51
52        let factors = TriggerFactors::new(
53            runtime_config.state_dir(),
54            config.working_dir.clone(),
55            args.allow_transient_write,
56            args.experimental_wasi_otel,
57            spin_version,
58        )
59        .context("failed to create factors")?;
60        Ok((factors, runtime_config))
61    }
62
63    fn configure_app<U: Send + 'static>(
64        executor: &mut FactorsExecutor<Self::Factors, U>,
65        runtime_config: &Self::RuntimeConfig,
66        config: &FactorsConfig,
67        args: &Self::CliArgs,
68    ) -> anyhow::Result<()> {
69        executor.add_hooks(StdioLoggingExecutorHooks::new(
70            config.follow_components.clone(),
71            runtime_config.log_dir(),
72            config.truncate_logs,
73        ));
74        executor.add_hooks(SqlStatementExecutorHook::new(
75            args.sqlite_statements.clone(),
76        ));
77        executor.add_hooks(InitialKvSetterHook::new(args.key_values.clone()));
78        executor.add_hooks(SqliteDefaultStoreSummaryHook);
79        executor.add_hooks(KeyValueDefaultStoreSummaryHook);
80        executor.add_hooks(VariablesValidatorHook);
81
82        let max_instance_memory = args
83            .max_instance_memory
84            .or(runtime_config.max_instance_memory());
85
86        // Only add the hook if a max instance memory size is specified via flag or runtime config.
87        if let Some(max_instance_memory) = max_instance_memory {
88            executor.add_hooks(MaxInstanceMemoryHook::new(max_instance_memory));
89        }
90
91        Ok(())
92    }
93}