Skip to content

Commit d156648

Browse files
authored
Merge pull request #2781 from lann/kv-summary-hook
Add KeyValueDefaultStoreSummaryHook
2 parents 756f3d1 + 833ad50 commit d156648

File tree

8 files changed

+67
-1
lines changed

8 files changed

+67
-1
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ pub struct AppState {
119119
component_allowed_stores: HashMap<String, HashSet<String>>,
120120
}
121121

122+
impl AppState {
123+
pub fn store_summary(&self, label: &str) -> Option<String> {
124+
self.store_manager.summary(label)
125+
}
126+
}
127+
122128
pub struct InstanceBuilder {
123129
/// The store manager for the app.
124130
///

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,14 @@ impl StoreManager for KeyValueAzureCosmos {
102102
fn is_defined(&self, _store_name: &str) -> bool {
103103
true
104104
}
105+
106+
fn summary(&self, _store_name: &str) -> Option<String> {
107+
let database = self.client.database_client().database_name();
108+
let collection = self.client.collection_name();
109+
Some(format!(
110+
"Azure CosmosDB database: {database}, collection: {collection}"
111+
))
112+
}
105113
}
106114

107115
struct AzureCosmosStore {

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ impl StoreManager for KeyValueRedis {
4747
fn is_defined(&self, _store_name: &str) -> bool {
4848
true
4949
}
50+
51+
fn summary(&self, _store_name: &str) -> Option<String> {
52+
let redis::ConnectionInfo { addr, .. } = self.database_url.as_str().parse().ok()?;
53+
Some(format!("Redis at {addr}"))
54+
}
5055
}
5156

5257
struct RedisStore {

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ impl StoreManager for KeyValueSqlite {
6868
fn is_defined(&self, _store_name: &str) -> bool {
6969
true
7070
}
71+
72+
fn summary(&self, _store_name: &str) -> Option<String> {
73+
Some(match &self.location {
74+
DatabaseLocation::InMemory => "a temporary in-memory store".into(),
75+
DatabaseLocation::Path(path) => format!("\"{}\"", path.display()),
76+
})
77+
}
7178
}
7279

7380
struct SqliteStore {

crates/key-value/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ pub use key_value::Error;
2323
pub trait StoreManager: Sync + Send {
2424
async fn get(&self, name: &str) -> Result<Arc<dyn Store>, Error>;
2525
fn is_defined(&self, store_name: &str) -> bool;
26+
27+
/// A human-readable summary of the given store's configuration
28+
///
29+
/// Example: "Redis at localhost:1234"
30+
fn summary(&self, store_name: &str) -> Option<String> {
31+
let _ = store_name;
32+
None
33+
}
2634
}
2735

2836
#[async_trait]

crates/key-value/src/util.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ impl StoreManager for DelegatingStoreManager {
6666
fn is_defined(&self, store_name: &str) -> bool {
6767
self.delegates.contains_key(store_name)
6868
}
69+
70+
fn summary(&self, store_name: &str) -> Option<String> {
71+
(self.default_manager)(store_name)?.summary(store_name)
72+
}
6973
}
7074

7175
/// Wrap each `Store` produced by the inner `StoreManager` in an asynchronous, write-behind cache.
@@ -122,6 +126,10 @@ impl<T: StoreManager> StoreManager for CachingStoreManager<T> {
122126
fn is_defined(&self, store_name: &str) -> bool {
123127
self.inner.is_defined(store_name)
124128
}
129+
130+
fn summary(&self, store_name: &str) -> Option<String> {
131+
self.inner.summary(store_name)
132+
}
125133
}
126134

127135
struct CachingStoreState {

crates/trigger/src/cli.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod launch_metadata;
2+
mod summary;
23

34
use std::future::Future;
45
use std::path::{Path, PathBuf};
@@ -12,6 +13,7 @@ use spin_common::{arg_parser::parse_kv, sloth};
1213
use spin_core::async_trait;
1314
use spin_factors_executor::{ComponentLoader, FactorsExecutor};
1415
use spin_runtime_config::{ResolvedRuntimeConfig, UserProvidedPath};
16+
use summary::KeyValueDefaultStoreSummaryHook;
1517

1618
use crate::factors::{TriggerFactors, TriggerFactorsRuntimeConfig};
1719
use crate::stdio::{FollowComponents, StdioLoggingExecutorHooks};
@@ -418,7 +420,7 @@ impl<T: Trigger> TriggerAppBuilder<T> {
418420
));
419421
// TODO:
420422
// builder.hooks(SummariseRuntimeConfigHook::new(&self.runtime_config_file));
421-
// builder.hooks(KeyValuePersistenceMessageHook);
423+
executor.add_hooks(KeyValueDefaultStoreSummaryHook);
422424
// builder.hooks(SqlitePersistenceMessageHook);
423425

424426
let configured_app = {

crates/trigger/src/cli/summary.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use spin_factor_key_value::KeyValueFactor;
2+
use spin_factors_executor::ExecutorHooks;
3+
4+
use crate::factors::TriggerFactors;
5+
6+
pub struct KeyValueDefaultStoreSummaryHook;
7+
8+
impl<U> ExecutorHooks<TriggerFactors, U> for KeyValueDefaultStoreSummaryHook {
9+
fn configure_app(
10+
&mut self,
11+
configured_app: &spin_factors::ConfiguredApp<TriggerFactors>,
12+
) -> anyhow::Result<()> {
13+
if let Some(default_store_summary) = configured_app
14+
.app_state::<KeyValueFactor>()
15+
.ok()
16+
.and_then(|kv_state| kv_state.store_summary("default"))
17+
{
18+
println!("Storing default key-value data to {default_store_summary}.");
19+
}
20+
Ok(())
21+
}
22+
}

0 commit comments

Comments
 (0)