Skip to content

Commit 69e93e5

Browse files
committed
Make ExecutorHooks an async trait
Signed-off-by: Ryan Levick <[email protected]>
1 parent 0708080 commit 69e93e5

File tree

4 files changed

+65
-48
lines changed

4 files changed

+65
-48
lines changed

crates/factors-executor/src/lib.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ impl<T: RuntimeFactors, U: Send + 'static> FactorsExecutor<T, U> {
3232
hooks: Default::default(),
3333
})
3434
}
35+
}
3536

37+
impl<T: RuntimeFactors, U: Send + 'static> FactorsExecutor<T, U>
38+
where
39+
T::AppState: Sync,
40+
{
3641
/// Adds the given [`ExecutorHooks`] to this executor.
3742
///
3843
/// Hooks are run in the order they are added.
@@ -53,7 +58,7 @@ impl<T: RuntimeFactors, U: Send + 'static> FactorsExecutor<T, U> {
5358
.context("failed to configure app")?;
5459

5560
for hooks in &mut self.hooks {
56-
hooks.configure_app(&configured_app)?;
61+
hooks.configure_app(&configured_app).await?;
5762
}
5863

5964
let mut component_instance_pres = HashMap::new();
@@ -75,9 +80,14 @@ impl<T: RuntimeFactors, U: Send + 'static> FactorsExecutor<T, U> {
7580
}
7681
}
7782

78-
pub trait ExecutorHooks<T: RuntimeFactors, U>: Send + Sync {
83+
#[async_trait]
84+
pub trait ExecutorHooks<T, U>: Send + Sync
85+
where
86+
T: RuntimeFactors,
87+
T::AppState: Sync,
88+
{
7989
/// Configure app hooks run immediately after [`RuntimeFactors::configure_app`].
80-
fn configure_app(&mut self, configured_app: &ConfiguredApp<T>) -> anyhow::Result<()> {
90+
async fn configure_app(&mut self, configured_app: &ConfiguredApp<T>) -> anyhow::Result<()> {
8191
let _ = configured_app;
8292
Ok(())
8393
}
@@ -131,7 +141,12 @@ impl<T: RuntimeFactors, U: Send + 'static> FactorsExecutorApp<T, U> {
131141
.with_context(|| format!("no such component {component_id:?}"))?;
132142
Ok(instance_pre.component())
133143
}
144+
}
134145

146+
impl<T: RuntimeFactors, U: Send + 'static> FactorsExecutorApp<T, U>
147+
where
148+
T::AppState: Sync,
149+
{
135150
/// Returns an instance builder for the given component ID.
136151
pub fn prepare(&self, component_id: &str) -> anyhow::Result<FactorsInstanceBuilder<T, U>> {
137152
let app_component = self

crates/trigger/src/cli/sqlite_statements.rs

Lines changed: 41 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use anyhow::Context as _;
2+
use spin_core::async_trait;
23
use spin_factor_sqlite::SqliteFactor;
34
use spin_factors::RuntimeFactors;
45
use spin_factors_executor::ExecutorHooks;
@@ -21,68 +22,65 @@ impl SqlStatementExecutorHook {
2122
pub fn new(sql_statements: Vec<String>) -> Self {
2223
Self { sql_statements }
2324
}
24-
}
2525

26-
impl<F: RuntimeFactors, U> ExecutorHooks<F, U> for SqlStatementExecutorHook {
27-
fn configure_app(
28-
&mut self,
29-
configured_app: &spin_factors::ConfiguredApp<F>,
30-
) -> anyhow::Result<()> {
26+
/// Executes the sql statements.
27+
pub async fn execute(&self, sqlite: &spin_factor_sqlite::AppState) -> anyhow::Result<()> {
3128
if self.sql_statements.is_empty() {
3229
return Ok(());
3330
}
34-
let Some(sqlite) = configured_app.app_state::<SqliteFactor>().ok() else {
35-
return Ok(());
36-
};
37-
if let Ok(current) = tokio::runtime::Handle::try_current() {
38-
let _ = current.spawn(execute(sqlite.clone(), self.sql_statements.clone()));
39-
}
40-
Ok(())
41-
}
42-
}
43-
44-
/// Executes the sql statements.
45-
pub async fn execute(
46-
sqlite: spin_factor_sqlite::AppState,
47-
sql_statements: Vec<String>,
48-
) -> anyhow::Result<()> {
49-
let get_database = |label| {
50-
let sqlite = &sqlite;
51-
async move {
31+
let get_database = |label| async move {
5232
sqlite
5333
.get_connection(label)
5434
.await
5535
.transpose()
5636
.with_context(|| format!("failed connect to database with label '{label}'"))
57-
}
58-
};
37+
};
5938

60-
for statement in &sql_statements {
61-
if let Some(config) = statement.strip_prefix('@') {
62-
let (file, label) = parse_file_and_label(config)?;
63-
let database = get_database(label).await?.with_context(|| {
39+
for statement in &self.sql_statements {
40+
if let Some(config) = statement.strip_prefix('@') {
41+
let (file, label) = parse_file_and_label(config)?;
42+
let database = get_database(label).await?.with_context(|| {
6443
format!(
6544
"based on the '@{config}' a registered database named '{label}' was expected but not found."
6645
)
6746
})?;
68-
let sql = std::fs::read_to_string(file).with_context(|| {
69-
format!("could not read file '{file}' containing sql statements")
70-
})?;
71-
database.execute_batch(&sql).await.with_context(|| {
72-
format!("failed to execute sql against database '{label}' from file '{file}'")
73-
})?;
74-
} else {
75-
let Some(default) = get_database(DEFAULT_SQLITE_LABEL).await? else {
76-
debug_assert!(false, "the '{DEFAULT_SQLITE_LABEL}' sqlite database should always be available but for some reason was not");
77-
return Ok(());
78-
};
79-
default
47+
let sql = std::fs::read_to_string(file).with_context(|| {
48+
format!("could not read file '{file}' containing sql statements")
49+
})?;
50+
database.execute_batch(&sql).await.with_context(|| {
51+
format!("failed to execute sql against database '{label}' from file '{file}'")
52+
})?;
53+
} else {
54+
let Some(default) = get_database(DEFAULT_SQLITE_LABEL).await? else {
55+
debug_assert!(false, "the '{DEFAULT_SQLITE_LABEL}' sqlite database should always be available but for some reason was not");
56+
return Ok(());
57+
};
58+
default
8059
.query(statement, Vec::new())
8160
.await
8261
.with_context(|| format!("failed to execute following sql statement against default database: '{statement}'"))?;
62+
}
8363
}
64+
Ok(())
65+
}
66+
}
67+
68+
#[async_trait]
69+
impl<F, U> ExecutorHooks<F, U> for SqlStatementExecutorHook
70+
where
71+
F: RuntimeFactors,
72+
F::AppState: Sync,
73+
{
74+
async fn configure_app(
75+
&mut self,
76+
configured_app: &spin_factors::ConfiguredApp<F>,
77+
) -> anyhow::Result<()> {
78+
let Some(sqlite) = configured_app.app_state::<SqliteFactor>().ok() else {
79+
return Ok(());
80+
};
81+
self.execute(&sqlite).await?;
82+
Ok(())
8483
}
85-
Ok(())
8684
}
8785

8886
/// Parses a @{file:label} sqlite statement

crates/trigger/src/cli/summary.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
use spin_core::async_trait;
12
use spin_factor_key_value::KeyValueFactor;
23
use spin_factors_executor::ExecutorHooks;
34

45
use crate::factors::TriggerFactors;
56

67
pub struct KeyValueDefaultStoreSummaryHook;
78

9+
#[async_trait]
810
impl<U> ExecutorHooks<TriggerFactors, U> for KeyValueDefaultStoreSummaryHook {
9-
fn configure_app(
11+
async fn configure_app(
1012
&mut self,
1113
configured_app: &spin_factors::ConfiguredApp<TriggerFactors>,
1214
) -> anyhow::Result<()> {

crates/trigger/src/stdio.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::{
66

77
use anyhow::{Context, Result};
88
use spin_common::ui::quoted_path;
9+
use spin_core::async_trait;
910
use spin_factors_executor::ExecutorHooks;
1011
use tokio::io::AsyncWrite;
1112

@@ -87,8 +88,9 @@ impl StdioLoggingExecutorHooks {
8788
}
8889
}
8990

91+
#[async_trait]
9092
impl<U> ExecutorHooks<TriggerFactors, U> for StdioLoggingExecutorHooks {
91-
fn configure_app(
93+
async fn configure_app(
9294
&mut self,
9395
configured_app: &spin_factors::ConfiguredApp<TriggerFactors>,
9496
) -> anyhow::Result<()> {

0 commit comments

Comments
 (0)