Skip to content

Commit 14ff488

Browse files
authored
Merge pull request #89 from movementlabsxyz/l-monninger/88
chore: type safe API for embedded Aptos runner
2 parents 5322d0e + 54e16f4 commit 14ff488

File tree

11 files changed

+255
-60
lines changed

11 files changed

+255
-60
lines changed

Cargo.lock

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,12 @@ secure-signer-loader = { git = "https://github.com/movementlabsxyz/secure-signin
123123
secure-signer-aws-kms = { git = "https://github.com/movementlabsxyz/secure-signing.git", rev = "f37eebd6d494d21b26b2faa44e1188de42ff1007" }
124124

125125
# kestrel
126-
kestrel = { git = "https://github.com/movementlabsxyz/kestrel.git", rev = "8395e2dce55192269a41f5bacacedaf49555f875" }
127-
jsonlvar = { git = "https://github.com/movementlabsxyz/kestrel.git", rev = "8395e2dce55192269a41f5bacacedaf49555f875" }
128-
commander = { git = "https://github.com/movementlabsxyz/kestrel.git", rev = "8395e2dce55192269a41f5bacacedaf49555f875" }
129-
include-dir = { git = "https://github.com/movementlabsxyz/kestrel.git", rev = "8395e2dce55192269a41f5bacacedaf49555f875" }
130-
include-vendor = { git = "https://github.com/movementlabsxyz/kestrel.git", rev = "8395e2dce55192269a41f5bacacedaf49555f875" }
131-
ready-docker = { git = "https://github.com/movementlabsxyz/kestrel.git", rev = "8395e2dce55192269a41f5bacacedaf49555f875" }
126+
kestrel = { git = "https://github.com/movementlabsxyz/kestrel.git", rev = "96fa1a31088af992748c8dbe6b8fe4ccfba771fa" }
127+
jsonlvar = { git = "https://github.com/movementlabsxyz/kestrel.git", rev = "96fa1a31088af992748c8dbe6b8fe4ccfba771fa" }
128+
commander = { git = "https://github.com/movementlabsxyz/kestrel.git", rev = "96fa1a31088af992748c8dbe6b8fe4ccfba771fa" }
129+
include-dir = { git = "https://github.com/movementlabsxyz/kestrel.git", rev = "96fa1a31088af992748c8dbe6b8fe4ccfba771fa" }
130+
include-vendor = { git = "https://github.com/movementlabsxyz/kestrel.git", rev = "96fa1a31088af992748c8dbe6b8fe4ccfba771fa" }
131+
ready-docker = { git = "https://github.com/movementlabsxyz/kestrel.git", rev = "96fa1a31088af992748c8dbe6b8fe4ccfba771fa" }
132132

133133
# orfile
134134
orfile = { git = "https://github.com/movementlabsxyz/orfile.git", rev = "b49cb42495816fa00a1107be5bbf41aff3a8255d" }

checks/migrator/checks/sketchpad/src/example.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub mod test {
44
use mtma_migrator_test_types::check::checked_migration;
55
use mtma_migrator_types::migrator::MovementMigrator;
66
use mtma_node_null_core::config::Config as MtmaNullConfig;
7-
use mtma_node_test_types::prelude::{Prelude, PreludeError};
7+
use mtma_node_test_types::prelude::Prelude;
88

99
#[tokio::test]
1010
#[tracing_test::traced_test]

migration/util/migrator-types/src/migrator/movement_aptos_migrator.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use anyhow::Context;
22
use aptos_config::config::NodeConfig;
33
use aptos_rest_client::Client as MovementAptosRestClient;
44
use kestrel::WaitCondition;
5-
use movement_aptos_core::MovementAptos;
5+
use movement_aptos_core::{runtime, MovementAptos};
66
use mtma_node_types::executor::MovementAptosNode;
77

88
/// An enum supporting different types of runners.
@@ -12,7 +12,7 @@ use mtma_node_types::executor::MovementAptosNode;
1212
#[derive(Clone)]
1313
pub enum Runner {
1414
/// [MovementAptos] runner.
15-
MovementAptos(MovementAptos),
15+
MovementAptos(MovementAptos<runtime::TokioTest>),
1616
}
1717

1818
/// The [MovementAptos] migration struct as would be presented in the criterion.

util/movement-aptos/movement-aptos-core/src/config.rs

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
66
use std::path::PathBuf;
77
use std::str::FromStr;
88

9-
use crate::movement_aptos::MovementAptos;
9+
use crate::movement_aptos::{runtime, MovementAptos};
1010
use aptos_node::create_single_node_test_config;
1111

1212
#[derive(Debug, Serialize, Deserialize, Clone)]
@@ -66,11 +66,6 @@ pub struct Config {
6666
#[orfile(config)]
6767
#[clap(long)]
6868
pub log_file: Option<PathBuf>,
69-
70-
/// Whether to create a global rayon pool.
71-
#[orfile(config)]
72-
#[clap(long)]
73-
pub create_global_rayon_pool: bool,
7469
}
7570

7671
impl Config {
@@ -90,19 +85,15 @@ impl Config {
9085
)
9186
.map_err(|e| ConfigError::Internal(e.into()))?;
9287

93-
Ok(Config {
94-
node_config: NodeConfigWrapper(node_config),
95-
log_file: None,
96-
create_global_rayon_pool: false,
97-
})
88+
Ok(Config { node_config: NodeConfigWrapper(node_config), log_file: None })
9889
}
9990

10091
/// Builds the config into a [MovementAptos] runner.
101-
pub fn build(&self) -> Result<MovementAptos, ConfigError> {
102-
Ok(MovementAptos::new(
92+
pub fn build(&self) -> Result<MovementAptos<runtime::TokioTest>, ConfigError> {
93+
Ok(MovementAptos::<runtime::TokioTest>::try_new(
10394
self.node_config.0.clone(),
10495
self.log_file.clone(),
105-
self.create_global_rayon_pool,
106-
))
96+
)
97+
.map_err(|e| ConfigError::Internal(e.into()))?)
10798
}
10899
}

util/movement-aptos/movement-aptos-core/src/movement_aptos.rs

Lines changed: 73 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ use aptos_config::config::NodeConfig;
22
use kestrel::State;
33
use std::path::PathBuf;
44
pub mod rest_api;
5+
pub mod runtime;
56
pub use rest_api::RestApi;
67

8+
use runtime::Runtime;
9+
710
/// Errors thrown when running [MovementAptos].
811
#[derive(Debug, thiserror::Error)]
912
pub enum MovementAptosError {
@@ -12,28 +15,41 @@ pub enum MovementAptosError {
1215
}
1316

1417
#[derive(Clone)]
15-
pub struct MovementAptos {
18+
pub struct MovementAptos<R>
19+
where
20+
R: Runtime,
21+
{
1622
/// The [NodeConfig] for the Aptos node.
1723
pub node_config: NodeConfig,
1824
/// The path to the log file.
1925
pub log_file: Option<PathBuf>,
20-
/// Whether to create a global rayon pool.
21-
pub create_global_rayon_pool: bool,
26+
/// The runtime for the Aptos node.
27+
pub runtime: std::marker::PhantomData<R>,
2228
/// The [MovementAptosRestApi] for the Aptos node.
2329
pub rest_api: State<RestApi>,
2430
}
2531

26-
impl MovementAptos {
27-
pub fn new(
32+
impl<R> MovementAptos<R>
33+
where
34+
R: Runtime,
35+
{
36+
/// If you have something that marks your ability to get a runtime, you can use this.
37+
pub fn new(node_config: NodeConfig, log_file: Option<PathBuf>, _runtime: R) -> Self {
38+
Self { node_config, log_file, runtime: std::marker::PhantomData, rest_api: State::new() }
39+
}
40+
41+
/// Checks runtime availability and creates a new [MovementAptos].
42+
pub fn try_new(
2843
node_config: NodeConfig,
2944
log_file: Option<PathBuf>,
30-
create_global_rayon_pool: bool,
31-
) -> Self {
32-
Self { node_config, log_file, create_global_rayon_pool, rest_api: State::new() }
45+
) -> Result<Self, anyhow::Error> {
46+
let runtime = R::try_new()?;
47+
let movement_aptos = MovementAptos::new(node_config, log_file, runtime);
48+
Ok(movement_aptos)
3349
}
3450

3551
pub fn from_config(config: NodeConfig) -> Result<Self, anyhow::Error> {
36-
let movement_aptos = MovementAptos::new(config, None, false);
52+
let movement_aptos = MovementAptos::new(config, None, R::try_new()?);
3753
Ok(movement_aptos)
3854
}
3955

@@ -43,15 +59,37 @@ impl MovementAptos {
4359
}
4460

4561
/// Runs the internal node logic
46-
pub(crate) fn run_node(&self) -> Result<(), MovementAptosError> {
47-
aptos_node::start(
48-
self.node_config.clone(),
49-
self.log_file.clone(),
50-
self.create_global_rayon_pool,
51-
)
52-
.map_err(|e| MovementAptosError::Internal(e.into()))?;
53-
54-
Ok(())
62+
pub(crate) async fn run_node(&self) -> Result<(), MovementAptosError> {
63+
// Clone necessary data for the closure
64+
let node_config = self.node_config.clone();
65+
let log_file = self.log_file.clone();
66+
67+
// Spawn the blocking task
68+
let blocking_task_result = tokio::task::spawn_blocking(move || {
69+
// This closure runs on a blocking thread
70+
aptos_node::start(
71+
node_config,
72+
log_file,
73+
R::create_global_rayon_pool(), // Assuming R is in scope and its result is Send
74+
)
75+
// The closure should return the direct result from aptos_node::start.
76+
// The error type from aptos_node::start (let's call it AptosNodeError)
77+
// needs to be Send + 'static for the closure.
78+
})
79+
.await;
80+
81+
match blocking_task_result {
82+
Ok(Ok(())) => Ok(()), // aptos_node::start succeeded
83+
Ok(Err(aptos_node_err)) => {
84+
// aptos_node::start failed. We need aptos_node_err to be convertible
85+
// into the Box<dyn Error> for MovementAptosError::Internal.
86+
Err(MovementAptosError::Internal(aptos_node_err.into()))
87+
}
88+
Err(join_err) => {
89+
// spawn_blocking task failed (e.g., panicked or was cancelled by Tokio)
90+
Err(MovementAptosError::Internal(Box::new(join_err)))
91+
}
92+
}
5593
}
5694

5795
/// Runs the node and fills state.
@@ -66,18 +104,22 @@ impl MovementAptos {
66104

67105
let runner = self.clone();
68106
let runner_task = kestrel::task(async move {
69-
runner.run_node()?;
107+
runner.run_node().await?;
70108
Ok::<_, MovementAptosError>(())
71109
});
72110

73111
// rest api state
74112
let rest_api_state = self.rest_api.clone();
75113
let rest_api_polling = kestrel::task(async move {
76114
loop {
115+
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
116+
println!("POLLING REST API: {:?}", rest_api);
77117
// wait for the rest api to be ready
78118
let response = reqwest::get(rest_api.rest_api_url.clone())
79119
.await
80120
.map_err(|e| MovementAptosError::Internal(e.into()))?;
121+
122+
println!("REST API RESPONSE: {:?}", response);
81123
if response.status().is_success() {
82124
rest_api_state.write().set(rest_api).await;
83125
break;
@@ -102,7 +144,7 @@ mod tests {
102144
use rand::thread_rng;
103145
use std::path::Path;
104146

105-
#[tokio::test]
147+
#[tokio::test(flavor = "multi_thread")]
106148
async fn test_movement_aptos() -> Result<(), anyhow::Error> {
107149
// open in a new db
108150
let unique_id = uuid::Uuid::new_v4();
@@ -128,11 +170,20 @@ mod tests {
128170
rng,
129171
)?;
130172

131-
let movement_aptos = MovementAptos::new(node_config, None, false);
173+
let movement_aptos = MovementAptos::<runtime::TokioTest>::try_new(node_config, None)?;
132174
let rest_api_state = movement_aptos.rest_api().read().clone();
133-
movement_aptos.run().await?;
175+
176+
let movement_aptos_task = kestrel::task(async move {
177+
movement_aptos.run().await?;
178+
Ok::<_, MovementAptosError>(())
179+
});
180+
134181
rest_api_state.wait_for(tokio::time::Duration::from_secs(30)).await?;
135182

183+
println!("ENDING MOVEMENT APTOS");
184+
185+
kestrel::end!(movement_aptos_task)?;
186+
136187
Ok(())
137188
}
138189
}

0 commit comments

Comments
 (0)