Skip to content

Commit 99547a9

Browse files
committed
Add SqliteDefaultStoreSummaryHook
Signed-off-by: Lann Martin <[email protected]>
1 parent 1e3def5 commit 99547a9

File tree

7 files changed

+73
-12
lines changed

7 files changed

+73
-12
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,17 @@ pub struct AppState {
120120
}
121121

122122
impl AppState {
123+
/// Returns the [`StoreManager::summary`] for the given store label.
123124
pub fn store_summary(&self, label: &str) -> Option<String> {
124125
self.store_manager.summary(label)
125126
}
127+
128+
/// Returns true if the given store label is used by any component.
129+
pub fn store_is_used(&self, label: &str) -> bool {
130+
self.component_allowed_stores
131+
.values()
132+
.any(|stores| stores.contains(label))
133+
}
126134
}
127135

128136
pub struct InstanceBuilder {

crates/factor-sqlite/src/lib.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,17 @@ impl AppState {
169169
/// Get a connection for a given database label.
170170
///
171171
/// Returns `None` if there is no connection creator for the given label.
172-
pub async fn get_connection(
173-
&self,
174-
label: &str,
175-
) -> Option<Result<Box<dyn Connection>, v2::Error>> {
172+
pub fn get_connection(&self, label: &str) -> Option<Result<Box<dyn Connection>, v2::Error>> {
176173
let connection = (self.get_connection_creator)(label)?.create_connection();
177174
Some(connection)
178175
}
176+
177+
/// Returns true if the given database label is used by any component.
178+
pub fn database_is_used(&self, label: &str) -> bool {
179+
self.allowed_databases
180+
.values()
181+
.any(|stores| stores.contains(label))
182+
}
179183
}
180184

181185
/// A creator of a connections for a particular SQLite database.
@@ -205,4 +209,11 @@ pub trait Connection: Send + Sync {
205209
) -> Result<v2::QueryResult, v2::Error>;
206210

207211
async fn execute_batch(&self, statements: &str) -> anyhow::Result<()>;
212+
213+
/// A human-readable summary of the connection's configuration
214+
///
215+
/// Example: "libSQL at libsql://example.com"
216+
fn summary(&self) -> Option<String> {
217+
None
218+
}
208219
}

crates/sqlite-inproc/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ impl Connection for InProcConnection {
112112
async fn execute_batch(&self, statements: &str) -> anyhow::Result<()> {
113113
self.execute_batch(statements).await
114114
}
115+
116+
fn summary(&self) -> Option<String> {
117+
Some(match &self.location {
118+
InProcDatabaseLocation::InMemory => "a temporary in-memory database".to_string(),
119+
InProcDatabaseLocation::Path(path) => format!("\"{}\"", path.display()),
120+
})
121+
}
115122
}
116123

117124
fn execute_query(

crates/sqlite/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ impl Connection for LibSqlConnection {
166166
let client = self.get_client().await?;
167167
client.execute_batch(statements).await
168168
}
169+
170+
fn summary(&self) -> Option<String> {
171+
Some(format!("libSQL at {}", self.url))
172+
}
169173
}
170174

171175
/// Configuration for a local SQLite database.

crates/trigger/src/cli.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use spin_core::async_trait;
1515
use spin_factors_executor::{ComponentLoader, FactorsExecutor};
1616
use spin_runtime_config::{ResolvedRuntimeConfig, UserProvidedPath};
1717
use sqlite_statements::SqlStatementExecutorHook;
18-
use summary::KeyValueDefaultStoreSummaryHook;
18+
use summary::{KeyValueDefaultStoreSummaryHook, SqliteDefaultStoreSummaryHook};
1919

2020
use crate::factors::{TriggerFactors, TriggerFactorsRuntimeConfig};
2121
use crate::stdio::{FollowComponents, StdioLoggingExecutorHooks};
@@ -424,8 +424,8 @@ impl<T: Trigger> TriggerAppBuilder<T> {
424424
// TODO:
425425
// builder.hooks(SummariseRuntimeConfigHook::new(&self.runtime_config_file));
426426
executor.add_hooks(KeyValueDefaultStoreSummaryHook);
427+
executor.add_hooks(SqliteDefaultStoreSummaryHook);
427428
executor.add_hooks(SqlStatementExecutorHook::new(options.sqlite_statements));
428-
// builder.hooks(SqlitePersistenceMessageHook);
429429

430430
let configured_app = {
431431
let _sloth_guard = warn_if_wasm_build_slothful();

crates/trigger/src/cli/sqlite_statements.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ impl SqlStatementExecutorHook {
3131
let get_database = |label| async move {
3232
sqlite
3333
.get_connection(label)
34-
.await
3534
.transpose()
3635
.with_context(|| format!("failed connect to database with label '{label}'"))
3736
};

crates/trigger/src/cli/summary.rs

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use spin_core::async_trait;
22
use spin_factor_key_value::KeyValueFactor;
3+
use spin_factor_sqlite::SqliteFactor;
34
use spin_factors_executor::ExecutorHooks;
45

56
use crate::factors::TriggerFactors;
67

8+
/// An [`ExecutorHooks`] that prints information about the default KV store.
79
pub struct KeyValueDefaultStoreSummaryHook;
810

911
#[async_trait]
@@ -12,13 +14,43 @@ impl<U> ExecutorHooks<TriggerFactors, U> for KeyValueDefaultStoreSummaryHook {
1214
&mut self,
1315
configured_app: &spin_factors::ConfiguredApp<TriggerFactors>,
1416
) -> anyhow::Result<()> {
15-
if let Some(default_store_summary) = configured_app
16-
.app_state::<KeyValueFactor>()
17-
.ok()
18-
.and_then(|kv_state| kv_state.store_summary("default"))
19-
{
17+
let Ok(kv_app_state) = configured_app.app_state::<KeyValueFactor>() else {
18+
return Ok(());
19+
};
20+
if !kv_app_state.store_is_used("default") {
21+
// We don't talk about unused default stores
22+
return Ok(());
23+
}
24+
if let Some(default_store_summary) = kv_app_state.store_summary("default") {
2025
println!("Storing default key-value data to {default_store_summary}.");
2126
}
2227
Ok(())
2328
}
2429
}
30+
31+
/// An [`ExecutorHooks`] that prints information about the default KV store.
32+
pub struct SqliteDefaultStoreSummaryHook;
33+
34+
#[async_trait]
35+
impl<U> ExecutorHooks<TriggerFactors, U> for SqliteDefaultStoreSummaryHook {
36+
async fn configure_app(
37+
&mut self,
38+
configured_app: &spin_factors::ConfiguredApp<TriggerFactors>,
39+
) -> anyhow::Result<()> {
40+
let Ok(sqlite_app_state) = configured_app.app_state::<SqliteFactor>() else {
41+
return Ok(());
42+
};
43+
if !sqlite_app_state.database_is_used("default") {
44+
// We don't talk about unused default databases
45+
return Ok(());
46+
}
47+
if let Some(default_database_summary) = sqlite_app_state
48+
.get_connection("default")
49+
.and_then(Result::ok)
50+
.and_then(|conn| conn.summary())
51+
{
52+
println!("Storing default SQLite data to {default_database_summary}.");
53+
}
54+
Ok(())
55+
}
56+
}

0 commit comments

Comments
 (0)