Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

398 client runner #400

Merged
merged 21 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
432 changes: 343 additions & 89 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]
resolver = "2"
members = [
"clients/runner",
"clients/runtime",
"clients/runtime/client",
"clients/vault",
Expand Down
14 changes: 10 additions & 4 deletions clients/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ cargo build --features=parachain-metadata

## Running the vault

To run the vault with the provided standalone chain use:
To run the vault with the auto-updater service:

```
cargo run --bin runner -- --parachain-ws <parachain-ws> -- --keyring alice --stellar-vault-secret-key-filepath <secret_key_file_path> --stellar-overlay-config-filepath <cfg_file_path>```
```

To run the vault directly with the provided standalone chain use:

```
cargo run --bin vault --features standalone-metadata -- --keyring alice --stellar-vault-secret-key-filepath <secret_key_file_path> --stellar-overlay-config-filepath <cfg_file_path>
Expand Down Expand Up @@ -89,7 +95,7 @@ cargo test --test '*' --package vault --features integration-test
When any changes are made to elements associated with the pallets, such as extrinsic names or parameters, it is necessary to regenerate the metadata. Subxt is employed specifically for this purpose.

```
cargo install subxt-cli
cargo install subxt-cli@0.31.0

// fetching from an automatically detected local chain
subxt metadata -f bytes > runtime/metadata-{your-chain-name}.scale
Expand All @@ -106,10 +112,10 @@ After making the changes, the first step is to run the local node.
cargo run --bin spacewalk-standalone --release -- --dev
```

Once the local node is running, run this command:
Once the local node is running, run this command from the clients directory:
gianfra-t marked this conversation as resolved.
Show resolved Hide resolved

```
subxt metadata -f bytes > runtime/metadata-standalone.scale
subxt metadata -f bytes > runtime/metadata-standalone.scale --version 14
```

## Troubleshooting
Expand Down
32 changes: 32 additions & 0 deletions clients/runner/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[package]
name = "runner"
version = "0.1.0"
edition = "2021"


[dependencies]
clap = { version = "4.0.17", features = ["derive"]}
hex = "0.4.3"
tokio = { version = "1.8", features = ["rt-multi-thread", "macros", "time"] }
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full", "bit-vec"] }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" }
thiserror = "1.0.0"
log = "0.4.0"
env_logger = "0.7.1"
reqwest = "0.11.11"
# reuse version of `url` depended on by `reqwest`
url = "2.2.2"
nix = "0.24.2"
async-trait = "0.1.40"
bytes = "1.1.0"
signal-hook = "0.3.14"
signal-hook-tokio = { version = "0.3.1", features = ["futures-v0_3"] }
futures = "0.3.21"
backoff = { version = "0.3.0", features = ["tokio"] }
subxt = { version = "0.29.0", default_features = false, features = ["jsonrpsee-ws"] }
sha2 = "0.8.2"

[dev-dependencies]
sysinfo = "0.25.1"
tempdir = "0.3.7"
mockall = "0.8.1"
19 changes: 19 additions & 0 deletions clients/runner/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## Runner service

This service will constantly monitor for the on-chain storage information about the vault client.
If a new client is detected, it will download and replace the client currently running.
It will also monitor for vault processes status, if no process is detected it will attempt to execute the one matching with latest download form on chain release info.

## Command to run vault

Runner arguments, we can pass as many client/vault commands as necessary after runner-specific commands.

```cargo run --bin runner -- --parachain-ws <chain-ws> --download-path <path_for_download_client> -- <vault_commands>...```

Example running a vault for local spacewalk standalone:

```cargo run --bin runner -- --parachain-ws ws://127.0.0.1:9944 -- --keyring alice --stellar-vault-secret-key-filepath <secret_key_file_path> --stellar-overlay-config-filepath <cfg_file_path>```

## Runner service process diagram

![Alt text](image.png)
Binary file added clients/runner/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 49 additions & 0 deletions clients/runner/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#![allow(clippy::enum_variant_names)]

use backoff::Error as BackoffError;
use codec::Error as CodecError;
use nix::Error as OsError;
use reqwest::Error as ReqwestError;
use std::io::Error as IoError;
use subxt::Error as SubxtError;
use thiserror::Error;
use url::ParseError as UrlParseError;

#[derive(Error, Debug)]
pub enum Error {
#[error("CodecError: {0}")]
CodecError(#[from] CodecError),
#[error("System I/O error: {0}")]
IoError(#[from] IoError),
#[error("System command error: {0}")]
OsError(#[from] OsError),
#[error("HTTP request error: {0}")]
HttpError(#[from] ReqwestError),
#[error("UrlParseError: {0}")]
UrlParseError(#[from] UrlParseError),
#[error("SubxtError: {0}")]
SubxtError(#[from] SubxtError),
#[error("Integer conversion error")]
IntegerConversionError,
#[error("A client release has not been downloaded")]
NoDownloadedRelease,
#[error("A child process is already running")]
ChildProcessExists,
#[error("Failed to terminate child process")]
ProcessTerminationFailure,
#[error("Failed to parse the client-type CLI argument")]
ClientTypeParsingError,
#[error("Failed to derive the release name of the vault")]
ClientNameDerivationError,
#[error("Incorrect Checksum")]
IncorrectChecksum,
}

impl<E: Into<Error> + Sized> From<BackoffError<E>> for Error {
fn from(e: BackoffError<E>) -> Self {
match e {
BackoffError::Permanent(err) => err.into(),
BackoffError::Transient(err) => err.into(),
}
}
}
53 changes: 53 additions & 0 deletions clients/runner/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
mod error;
mod runner;

use clap::Parser;

use error::Error;

use futures::{FutureExt, TryFutureExt};
use runner::ClientType;
use signal_hook::consts::*;
use signal_hook_tokio::Signals;
use std::{fmt::Debug, path::PathBuf};

use crate::runner::{retry_with_log_async, subxt_api, Runner};

#[derive(Parser, Debug, Clone)]
#[clap(version, author, about, trailing_var_arg = true)]
pub struct Opts {
/// Client to run, one of: vault, oracle, faucet. Default is `vault`.
#[clap(long, default_value = "vault")]
pub client_type: ClientType,

/// Parachain websocket URL.
#[clap(long)]
pub parachain_ws: String,

/// Download path for the client executable.
#[clap(long, default_value = ".")]
pub download_path: PathBuf,

/// CLI arguments to pass to the client executable.
pub client_args: Vec<String>,
}

#[tokio::main]
async fn main() -> Result<(), Error> {
env_logger::init_from_env(
env_logger::Env::default()
.filter_or(env_logger::DEFAULT_FILTER_ENV, log::LevelFilter::Info.as_str()),
);
let opts: Opts = Opts::parse();
let rpc_client = retry_with_log_async(
|| subxt_api(&opts.parachain_ws).into_future().boxed(),
"Error fetching executable".to_string(),
)
.await?;
log::info!("Connected to the parachain");

let runner = Runner::new(rpc_client, opts);
let shutdown_signals = Signals::new([SIGHUP, SIGTERM, SIGINT, SIGQUIT])?;
Runner::run(Box::new(runner), shutdown_signals).await?;
Ok(())
}
Loading
Loading