diff --git a/crates/factor-key-value-spin/src/lib.rs b/crates/factor-key-value-spin/src/lib.rs index 636b6c491a..45d8a7fc71 100644 --- a/crates/factor-key-value-spin/src/lib.rs +++ b/crates/factor-key-value-spin/src/lib.rs @@ -3,7 +3,7 @@ use std::{ path::{Path, PathBuf}, }; -use anyhow::{bail, Context}; +use anyhow::Context as _; use serde::{Deserialize, Serialize}; use spin_factor_key_value::runtime_config::spin::MakeKeyValueStore; use spin_key_value_sqlite::{DatabaseLocation, KeyValueSqlite}; @@ -42,23 +42,20 @@ impl MakeKeyValueStore for SpinKeyValueStore { let path = resolve_relative_path(path, base_path); DatabaseLocation::Path(path) } - // If the base path is `None` but path is an absolute path, use the absolute path - (None, Some(path)) if path.is_absolute() => DatabaseLocation::Path(path.clone()), - // If the base path is `None` but path is a relative path, error out - (None, Some(path)) => { - bail!( - "key-value store path '{}' is relative, but no base path is set", - path.display() - ) - } + // If the base path is `None` but use the path without resolving relative to the base path. + (None, Some(path)) => DatabaseLocation::Path(path.clone()), // Otherwise, use an in-memory database (None | Some(_), None) => DatabaseLocation::InMemory, }; if let DatabaseLocation::Path(path) = &location { // Create the store's parent directory if necessary if let Some(parent) = path.parent().filter(|p| !p.exists()) { - fs::create_dir_all(parent) - .context("Failed to create key value store's parent directory")?; + fs::create_dir_all(parent).with_context(|| { + format!( + "failed to create key value store's parent directory: '{}", + parent.display() + ) + })?; } } Ok(KeyValueSqlite::new(location)) diff --git a/crates/key-value-sqlite/Cargo.toml b/crates/key-value-sqlite/Cargo.toml index 63f51862d0..ba7a89c29a 100644 --- a/crates/key-value-sqlite/Cargo.toml +++ b/crates/key-value-sqlite/Cargo.toml @@ -11,7 +11,7 @@ rusqlite = { version = "0.29.0", features = ["bundled"] } spin-core = { path = "../core" } spin-key-value = { path = "../key-value" } spin-world = { path = "../world" } -tokio = "1" +tokio = { version = "1", features = ["rt-multi-thread"] } tracing = { workspace = true } [lints] diff --git a/crates/key-value-sqlite/src/lib.rs b/crates/key-value-sqlite/src/lib.rs index 79e28dc8e2..e890c06def 100644 --- a/crates/key-value-sqlite/src/lib.rs +++ b/crates/key-value-sqlite/src/lib.rs @@ -22,6 +22,11 @@ pub struct KeyValueSqlite { } impl KeyValueSqlite { + /// Create a new `KeyValueSqlite` store manager. + /// + /// If location is `DatabaseLocation::InMemory`, the database will be created in memory. + /// If it's `DatabaseLocation::Path`, the database will be created at the specified path. + /// Relative paths will be resolved against the current working directory. pub fn new(location: DatabaseLocation) -> Self { Self { location, diff --git a/crates/key-value/src/util.rs b/crates/key-value/src/util.rs index b027b8d77b..9ba6ad8edd 100644 --- a/crates/key-value/src/util.rs +++ b/crates/key-value/src/util.rs @@ -68,6 +68,9 @@ impl StoreManager for DelegatingStoreManager { } fn summary(&self, store_name: &str) -> Option { + if let Some(store) = self.delegates.get(store_name) { + return store.summary(store_name); + } (self.default_manager)(store_name)?.summary(store_name) } } diff --git a/crates/runtime-config/src/lib.rs b/crates/runtime-config/src/lib.rs index 22484c4092..d1c9742388 100644 --- a/crates/runtime-config/src/lib.rs +++ b/crates/runtime-config/src/lib.rs @@ -120,10 +120,14 @@ where provided_log_dir: UserProvidedPath, use_gpu: bool, ) -> anyhow::Result { + let runtime_config_dir = runtime_config_path + .and_then(Path::parent) + .map(ToOwned::to_owned); let toml_resolver = TomlResolver::new(&toml, local_app_dir, provided_state_dir, provided_log_dir); - let tls_resolver = runtime_config_path.map(SpinTlsRuntimeConfig::new); - let key_value_config_resolver = key_value_config_resolver(toml_resolver.state_dir()?); + let tls_resolver = runtime_config_dir.clone().map(SpinTlsRuntimeConfig::new); + let key_value_config_resolver = + key_value_config_resolver(runtime_config_dir, toml_resolver.state_dir()?); let sqlite_config_resolver = sqlite_config_resolver(toml_resolver.state_dir()?) .context("failed to resolve sqlite runtime config")?; @@ -396,9 +400,11 @@ const DEFAULT_KEY_VALUE_STORE_LABEL: &str = "default"; /// The key-value runtime configuration resolver. /// /// Takes a base path that all local key-value stores which are configured with -/// relative paths will be relative to. +/// relative paths will be relative to. It also takes a default store base path +/// which will be used as the directory for the default store. pub fn key_value_config_resolver( local_store_base_path: Option, + default_store_base_path: Option, ) -> key_value::RuntimeConfigResolver { let mut key_value = key_value::RuntimeConfigResolver::new(); @@ -417,13 +423,12 @@ pub fn key_value_config_resolver( .unwrap(); // Add handling of "default" store. + let default_store_path = default_store_base_path.map(|p| p.join(DEFAULT_SPIN_STORE_FILENAME)); // Unwraps are safe because the store is known to be serializable as toml. key_value .add_default_store::( DEFAULT_KEY_VALUE_STORE_LABEL, - SpinKeyValueRuntimeConfig::new( - local_store_base_path.map(|p| p.join(DEFAULT_SPIN_STORE_FILENAME)), - ), + SpinKeyValueRuntimeConfig::new(default_store_path), ) .unwrap();