Skip to content

Commit

Permalink
✨ get chain id and block number
Browse files Browse the repository at this point in the history
  • Loading branch information
AbdelStark committed Jul 7, 2023
1 parent 052a6df commit 9a5ecce
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 44 deletions.
2 changes: 1 addition & 1 deletion crates/gatling/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "gatling"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
license = "MIT"
homepage = "https://github.com/keep-starknet-strange/gomu-gomu-no-gatling"
Expand Down
36 changes: 36 additions & 0 deletions crates/gatling/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,39 @@
[![Rust crate](https://img.shields.io/crates/v/galing.svg)](https://crates.io/crates/gatling)

Blazing fast tool to benchmark Starknet sequencers 🦀.

## Installation

### From source

```bash
git clone https://github.com/keep-starknet-strange/gomu-gomu-no-gatling
cd gomu-gomu-no-gatling
cargo install --path .
```

### From crates.io

```bash
cargo install --locked gatling
```

## Usage

```bash
gatling --help
```

### Configuration

> **TODO**: Add configuration options.
### Run a load test

```bash
gatling shoot --config-path config/rinnegan.toml
```

## License

Licensed under [MIT](LICENSE).
78 changes: 60 additions & 18 deletions crates/gatling/src/actions/shoot.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,75 @@
use crate::config::GatlingConfig;
use color_eyre::eyre::Result;
use log::{debug, info};
use log::info;
use starknet::{core::types::FieldElement, providers::Provider};

use starknet::providers::{jsonrpc::HttpTransport, JsonRpcClient};
use url::Url;

/// Shoot the load test simulation.
pub async fn shoot(config: &GatlingConfig) -> Result<()> {
pub async fn shoot(config: GatlingConfig) -> Result<SimulationReport> {
info!("starting simulation with config: {:?}", config);
let mut shooter = GatlingShooter::new(config)?;
let mut simulation_report = Default::default();
// Trigger the setup phase.
setup().await?;
shooter.setup(&mut simulation_report).await?;
// Run the simulation.
run().await?;
shooter.run(&mut simulation_report).await?;
// Trigger the teardown phase.
teardown().await?;
Ok(())
shooter.teardown(&mut simulation_report).await?;
Ok(simulation_report.clone())
}

pub struct GatlingShooter {
config: GatlingConfig,
starknet_rpc: JsonRpcClient<HttpTransport>,
}

/// Setup the simulation.
pub async fn setup() -> Result<()> {
debug!("setting up!");
Ok(())
impl GatlingShooter {
pub fn new(config: GatlingConfig) -> Result<Self> {
let starknet_rpc = starknet_rpc_provider(Url::parse(&config.rpc.url)?);
Ok(Self {
config,
starknet_rpc,
})
}

/// Setup the simulation.
async fn setup<'a>(&mut self, _simulation_report: &'a mut SimulationReport) -> Result<()> {
info!("setting up!");
let chain_id = self.starknet_rpc.chain_id().await?;
info!("chain id: {}", chain_id);
let block_number = self.starknet_rpc.block_number().await?;
info!("block number: {}", block_number);
Ok(())
}

/// Teardown the simulation.
async fn teardown<'a>(&mut self, _simulation_report: &'a mut SimulationReport) -> Result<()> {
info!("tearing down!");
Ok(())
}

/// Run the simulation.
async fn run<'a>(&mut self, _simulation_report: &'a mut SimulationReport) -> Result<()> {
info!("firing!");
let _fail_fast = self.config.simulation.fail_fast.unwrap_or(true);
Ok(())
}
}

/// Teardown the simulation.
pub async fn teardown() -> Result<()> {
debug!("tearing down!");
Ok(())
/// The simulation report.
#[derive(Debug, Default, Clone)]
pub struct SimulationReport {
pub chain_id: Option<FieldElement>,
pub block_number: Option<u64>,
}

/// Run the simulation.
pub async fn run() -> Result<()> {
debug!("firing!");
Ok(())
/// Create a StarkNet RPC provider from a URL.
/// # Arguments
/// * `rpc` - The URL of the StarkNet RPC provider.
/// # Returns
/// A StarkNet RPC provider.
fn starknet_rpc_provider(rpc: Url) -> JsonRpcClient<HttpTransport> {
JsonRpcClient::new(HttpTransport::new(rpc))
}
25 changes: 21 additions & 4 deletions crates/gatling/src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
//! Defines the CLI commands.

// Imports
use clap::{Parser, Subcommand};
use clap::{Args, Parser, Subcommand};

const VERSION_STRING: &str = concat!(env!("CARGO_PKG_VERSION"));

/// Main CLI struct
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
#[command(
author,
version = VERSION_STRING,
about,
long_about = "Gomu Gomu no Gatling is a load testing tool for Starknet RPC endpoints."
)]
pub struct Cli {
#[clap(flatten)]
pub global_opts: GlobalOpts,

/// The subcommand to run.
#[command(subcommand)]
pub command: Option<Commands>,
pub command: Command,
}

/// Subcommands
#[derive(Subcommand, Debug)]
pub enum Commands {
pub enum Command {
/// Trigger a load test.
Shoot {},
}

#[derive(Debug, Args)]
pub struct GlobalOpts {
/// Configuration file path, optional.
#[clap(short, long, global = true)]
pub config_path: Option<String>,
}
36 changes: 25 additions & 11 deletions crates/gatling/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,56 @@
//! General configuration

use color_eyre::eyre::Result;
use config::{Config, File};
use config::{builder::DefaultState, Config, ConfigBuilder, File};
use serde_derive::Deserialize;

/// Configuration for the application.
#[derive(Debug, Deserialize)]
pub struct GatlingConfig {
/// The RPC configuration.
_rpc: Rpc,
pub rpc: Rpc,
/// The simulation configuration.
_simulation: Simulation,
pub simulation: Simulation,
}

#[derive(Debug, Deserialize)]
#[allow(unused)]
struct Rpc {
pub struct Rpc {
pub url: String,
}

#[derive(Debug, Deserialize)]
#[allow(unused)]
struct Simulation {
pub struct Simulation {
pub fail_fast: Option<bool>,
}

impl GatlingConfig {
/// Create a new configuration from environment variables.
pub fn new() -> Result<Self> {
Config::builder()
// Start off by merging in the "default" configuration file
.add_source(File::with_name("config/default"))
// Add in settings from the environment (with a prefix of GATLING)
// Eg.. `GATLING_FAIL_FAST=1 ./target/app` would set the `fail_fast` key
.add_source(config::Environment::with_prefix("gatling"))
base_config_builder()
.build()
.unwrap()
.try_deserialize()
.map_err(|e| e.into())
}

/// Create a new configuration from a file.
pub fn from_file(path: &str) -> Result<Self> {
base_config_builder()
.add_source(File::with_name(path))
.build()
.unwrap()
.try_deserialize()
.map_err(|e| e.into())
}
}

fn base_config_builder() -> ConfigBuilder<DefaultState> {
Config::builder()
// Start off by merging in the "default" configuration file
.add_source(File::with_name("config/default"))
// Add in settings from the environment (with a prefix of GATLING)
// Eg.. `GATLING_FAIL_FAST=1 ./target/app` would set the `fail_fast` key
.add_source(config::Environment::with_prefix("gatling"))
}
20 changes: 10 additions & 10 deletions crates/gatling/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use color_eyre::eyre::Result;
use dotenv::dotenv;
use gatling::{
actions::shoot::shoot,
cli::{Cli, Commands},
cli::{Cli, Command},
config::GatlingConfig,
};

Expand All @@ -20,23 +20,23 @@ async fn main() -> Result<()> {
// Load the environment variables from the .env file.
dotenv().ok();

// Retrieve the application configuration.
let cfg = GatlingConfig::new()?;

info!("Starting Gomu Gomu no Gatling...");

// Parse the command line arguments.
let cli = Cli::parse();

// Retrieve the application configuration.
let cfg = match cli.global_opts.config_path {
Some(path) => GatlingConfig::from_file(&path)?,
None => GatlingConfig::new()?,
};

// Execute the command.
match cli.command {
Some(command) => match command {
Commands::Shoot {} => shoot(&cfg).await?,
},
None => {
info!("nothing to do there, bye 👋");
Command::Shoot { .. } => {
let simulation_report = shoot(cfg).await?;
info!("simulation completed: {:?}", simulation_report);
}
}

Ok(())
}

0 comments on commit 9a5ecce

Please sign in to comment.