Skip to content

Commit dab87ce

Browse files
committed
Make sure resolved state_dir is used everywhere
Signed-off-by: Ryan Levick <[email protected]>
1 parent 7c4b268 commit dab87ce

File tree

8 files changed

+187
-120
lines changed

8 files changed

+187
-120
lines changed

crates/factor-key-value-spin/src/lib.rs

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::{
33
path::{Path, PathBuf},
44
};
55

6-
use anyhow::Context;
6+
use anyhow::{bail, Context};
77
use serde::{Deserialize, Serialize};
88
use spin_factor_key_value::runtime_config::spin::MakeKeyValueStore;
99
use spin_key_value_sqlite::{DatabaseLocation, KeyValueSqlite};
@@ -25,26 +25,6 @@ impl SpinKeyValueStore {
2525
}
2626
}
2727

28-
/// Runtime configuration for the SQLite key-value store.
29-
#[derive(Deserialize, Serialize)]
30-
pub struct SpinKeyValueRuntimeConfig {
31-
/// The path to the SQLite database file.
32-
path: Option<PathBuf>,
33-
}
34-
35-
impl SpinKeyValueRuntimeConfig {
36-
/// The default filename for the SQLite database.
37-
const DEFAULT_SPIN_STORE_FILENAME: &'static str = "sqlite_key_value.db";
38-
}
39-
40-
impl Default for SpinKeyValueRuntimeConfig {
41-
fn default() -> Self {
42-
Self {
43-
path: Some(PathBuf::from(Self::DEFAULT_SPIN_STORE_FILENAME)),
44-
}
45-
}
46-
}
47-
4828
impl MakeKeyValueStore for SpinKeyValueStore {
4929
const RUNTIME_CONFIG_TYPE: &'static str = "spin";
5030

@@ -56,24 +36,50 @@ impl MakeKeyValueStore for SpinKeyValueStore {
5636
&self,
5737
runtime_config: Self::RuntimeConfig,
5838
) -> anyhow::Result<Self::StoreManager> {
59-
// The base path and the subpath must both be set otherwise, we default to in-memory.
60-
let location =
61-
if let (Some(base_path), Some(path)) = (&self.base_path, &runtime_config.path) {
39+
let location = match (&self.base_path, &runtime_config.path) {
40+
// If both the base path and the path are specified, resolve the path against the base path
41+
(Some(base_path), Some(path)) => {
6242
let path = resolve_relative_path(path, base_path);
63-
// Create the store's parent directory if necessary
64-
let parent = path.parent().unwrap();
65-
if !parent.exists() {
66-
fs::create_dir_all(parent)
67-
.context("Failed to create key value store's parent directory")?;
68-
}
6943
DatabaseLocation::Path(path)
70-
} else {
71-
DatabaseLocation::InMemory
72-
};
44+
}
45+
// If the base path is `None` but path is an absolute path, use the absolute path
46+
(None, Some(path)) if path.is_absolute() => DatabaseLocation::Path(path.clone()),
47+
// If the base path is `None` but path is a relative path, error out
48+
(None, Some(path)) => {
49+
bail!(
50+
"key-value store path '{}' is relative, but no base path is set",
51+
path.display()
52+
)
53+
}
54+
// Otherwise, use an in-memory database
55+
(None | Some(_), None) => DatabaseLocation::InMemory,
56+
};
57+
if let DatabaseLocation::Path(path) = &location {
58+
// Create the store's parent directory if necessary
59+
if let Some(parent) = path.parent().filter(|p| !p.exists()) {
60+
fs::create_dir_all(parent)
61+
.context("Failed to create key value store's parent directory")?;
62+
}
63+
}
7364
Ok(KeyValueSqlite::new(location))
7465
}
7566
}
7667

68+
/// The serialized runtime configuration for the SQLite key-value store.
69+
#[derive(Deserialize, Serialize)]
70+
pub struct SpinKeyValueRuntimeConfig {
71+
/// The path to the SQLite database file.
72+
path: Option<PathBuf>,
73+
}
74+
75+
impl SpinKeyValueRuntimeConfig {
76+
/// Create a new SpinKeyValueRuntimeConfig with the given parent directory
77+
/// where the key-value store will live.
78+
pub fn new(path: Option<PathBuf>) -> Self {
79+
Self { path }
80+
}
81+
}
82+
7783
/// Resolve a relative path against a base dir.
7884
///
7985
/// If the path is absolute, it is returned as is. Otherwise, it is resolved against the base dir.

crates/factor-key-value/src/runtime_config/spin.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@ type StoreFromToml =
2828
/// Creates a `StoreFromToml` function from a `MakeKeyValueStore` implementation.
2929
fn store_from_toml_fn<T: MakeKeyValueStore>(provider_type: T) -> StoreFromToml {
3030
Arc::new(move |table| {
31-
let runtime_config: T::RuntimeConfig =
32-
table.try_into().context("could not parse runtime config")?;
31+
let runtime_config: T::RuntimeConfig = table
32+
.try_into()
33+
.context("could not parse key-value runtime config")?;
3334
let provider = provider_type
3435
.make_store(runtime_config)
35-
.context("could not make store")?;
36+
.context("could not make key-value store from runtime config")?;
3637
Ok(Arc::new(provider))
3738
})
3839
}
@@ -108,7 +109,9 @@ impl RuntimeConfigResolver {
108109

109110
let mut runtime_config = RuntimeConfig::default();
110111
for (label, config) in table {
111-
let store_manager = self.store_manager_from_config(config)?;
112+
let store_manager = self.store_manager_from_config(config).with_context(|| {
113+
format!("could not configure key-value store with label '{label}'")
114+
})?;
112115
runtime_config.add_store_manager(label.clone(), store_manager);
113116
}
114117
Ok(Some(runtime_config))
@@ -133,6 +136,8 @@ impl RuntimeConfigResolver {
133136
impl DefaultLabelResolver for RuntimeConfigResolver {
134137
fn default(&self, label: &str) -> Option<Arc<dyn StoreManager>> {
135138
let config = self.defaults.get(label)?;
139+
// TODO(rylev): The unwrap here is not ideal. We should return a Result instead.
140+
// Piping that through `DefaultLabelResolver` is a bit awkward, though.
136141
Some(self.store_manager_from_config(config.clone()).unwrap())
137142
}
138143
}

crates/factor-key-value/tests/factor_test.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use spin_factor_key_value::{
44
KeyValueFactor, RuntimeConfig,
55
};
66
use spin_factor_key_value_redis::RedisKeyValueStore;
7-
use spin_factor_key_value_spin::SpinKeyValueStore;
7+
use spin_factor_key_value_spin::{SpinKeyValueRuntimeConfig, SpinKeyValueStore};
88
use spin_factors::{FactorRuntimeConfigSource, RuntimeConfigSourceFinalizer, RuntimeFactors};
99
use spin_factors_test::{toml, TestEnvironment};
1010
use spin_world::v2::key_value::HostStore;
@@ -19,7 +19,8 @@ struct TestFactors {
1919
async fn default_key_value_works() -> anyhow::Result<()> {
2020
let mut test_resolver = RuntimeConfigResolver::new();
2121
test_resolver.register_store_type(SpinKeyValueStore::new(None))?;
22-
test_resolver.add_default_store::<SpinKeyValueStore>("default", Default::default())?;
22+
test_resolver
23+
.add_default_store::<SpinKeyValueStore>("default", SpinKeyValueRuntimeConfig::new(None))?;
2324
let factors = TestFactors {
2425
key_value: KeyValueFactor::new(test_resolver),
2526
};

crates/factors/src/runtime_config/toml.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ impl GetTomlValue for toml::Table {
1313
}
1414
}
1515

16+
#[derive(Debug, Clone)]
1617
/// A helper for tracking which keys have been used in a TOML table.
1718
pub struct TomlKeyTracker<'a> {
1819
unused_keys: RefCell<HashSet<&'a str>>,

crates/factors/tests/smoke.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use http_body_util::BodyExt;
55
use spin_app::App;
66
use spin_factor_key_value::{runtime_config::spin::RuntimeConfigResolver, KeyValueFactor};
77
use spin_factor_key_value_redis::RedisKeyValueStore;
8-
use spin_factor_key_value_spin::SpinKeyValueStore;
8+
use spin_factor_key_value_spin::{SpinKeyValueRuntimeConfig, SpinKeyValueStore};
99
use spin_factor_outbound_http::OutboundHttpFactor;
1010
use spin_factor_outbound_networking::OutboundNetworkingFactor;
1111
use spin_factor_variables::VariablesFactor;
@@ -39,7 +39,8 @@ impl AsInstanceState<FactorsInstanceState> for Data {
3939
#[tokio::test(flavor = "multi_thread")]
4040
async fn smoke_test_works() -> anyhow::Result<()> {
4141
let mut key_value_resolver = RuntimeConfigResolver::default();
42-
key_value_resolver.add_default_store::<SpinKeyValueStore>("default", Default::default())?;
42+
key_value_resolver
43+
.add_default_store::<SpinKeyValueStore>("default", SpinKeyValueRuntimeConfig::new(None))?;
4344
key_value_resolver.register_store_type(SpinKeyValueStore::new(Some(
4445
std::env::current_dir().context("failed to get current directory")?,
4546
)))?;

0 commit comments

Comments
 (0)