@@ -3,41 +3,79 @@ use std::{
33 path:: { Path , PathBuf } ,
44} ;
55
6- use anyhow:: Context ;
6+ use anyhow:: { bail , Context } ;
77use serde:: { Deserialize , Serialize } ;
88use spin_factor_key_value:: runtime_config:: spin:: MakeKeyValueStore ;
99use spin_key_value_sqlite:: { DatabaseLocation , KeyValueSqlite } ;
1010
1111/// A key-value store that uses SQLite as the backend.
1212pub struct SpinKeyValueStore {
1313 /// The base path or directory for the SQLite database file.
14- base_path : PathBuf ,
14+ base_path : Option < PathBuf > ,
1515}
1616
1717impl SpinKeyValueStore {
1818 /// Create a new SpinKeyValueStore with the given base path.
19- pub fn new ( base_path : PathBuf ) -> Self {
19+ ///
20+ /// If the database directory is None, the database will always be in-memory.
21+ /// If it's `Some`, the database will be stored at the combined `base_path` and
22+ /// the `path` specified in the runtime configuration.
23+ pub fn new ( base_path : Option < PathBuf > ) -> Self {
2024 Self { base_path }
2125 }
2226}
2327
24- /// Runtime configuration for the SQLite key-value store.
28+ impl MakeKeyValueStore for SpinKeyValueStore {
29+ const RUNTIME_CONFIG_TYPE : & ' static str = "spin" ;
30+
31+ type RuntimeConfig = SpinKeyValueRuntimeConfig ;
32+
33+ type StoreManager = KeyValueSqlite ;
34+
35+ fn make_store (
36+ & self ,
37+ runtime_config : Self :: RuntimeConfig ,
38+ ) -> anyhow:: Result < Self :: StoreManager > {
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) ) => {
42+ let path = resolve_relative_path ( path, base_path) ;
43+ DatabaseLocation :: Path ( path)
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+ }
64+ Ok ( KeyValueSqlite :: new ( location) )
65+ }
66+ }
67+
68+ /// The serialized runtime configuration for the SQLite key-value store.
2569#[ derive( Deserialize , Serialize ) ]
2670pub struct SpinKeyValueRuntimeConfig {
2771 /// The path to the SQLite database file.
2872 path : Option < PathBuf > ,
2973}
3074
3175impl SpinKeyValueRuntimeConfig {
32- /// The default filename for the SQLite database.
33- const DEFAULT_SPIN_STORE_FILENAME : & ' static str = "sqlite_key_value.db" ;
34-
35- /// Create a new runtime configuration with the given directory.
36- ///
37- /// If the database directory is None, the database is in-memory.
38- /// If the database directory is Some, the database is stored in a file in the given directory.
39- pub fn default ( default_database_dir : Option < PathBuf > ) -> Self {
40- let path = default_database_dir. map ( |dir| dir. join ( Self :: DEFAULT_SPIN_STORE_FILENAME ) ) ;
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 {
4179 Self { path }
4280 }
4381}
@@ -51,28 +89,3 @@ fn resolve_relative_path(path: &Path, base_dir: &Path) -> PathBuf {
5189 }
5290 base_dir. join ( path)
5391}
54-
55- impl MakeKeyValueStore for SpinKeyValueStore {
56- const RUNTIME_CONFIG_TYPE : & ' static str = "spin" ;
57-
58- type RuntimeConfig = SpinKeyValueRuntimeConfig ;
59-
60- type StoreManager = KeyValueSqlite ;
61-
62- fn make_store (
63- & self ,
64- runtime_config : Self :: RuntimeConfig ,
65- ) -> anyhow:: Result < Self :: StoreManager > {
66- let location = match runtime_config. path {
67- Some ( path) => {
68- let path = resolve_relative_path ( & path, & self . base_path ) ;
69- // Create the store's parent directory if necessary
70- fs:: create_dir_all ( path. parent ( ) . unwrap ( ) )
71- . context ( "Failed to create key value store" ) ?;
72- DatabaseLocation :: Path ( path)
73- }
74- None => DatabaseLocation :: InMemory ,
75- } ;
76- Ok ( KeyValueSqlite :: new ( location) )
77- }
78- }
0 commit comments